# Understanding the need for class variables and select type

**URL:** <https://fortran-lang.discourse.group/t/understanding-the-need-for-class-variables-and-select-type/2645>\
**Category:** Uncategorized\
**Created:** [January 24, 2022, 5:19pm UTC](https://fortran-lang.discourse.group/t/understanding-the-need-for-class-variables-and-select-type/2645 "2022-01-24T17:19:50Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [January 24, 2022, 5:19pm UTC](https://fortran-lang.discourse.group/t/understanding-the-need-for-class-variables-and-select-type/2645/1 "2022-01-24T17:19:50Z")

</div>

I have no experience with OOP in any language and am trying to understand how it works in Fortran. Trying some code, it seemed that Fortran required `select type` for a class variable even when the type should be known at compile time. I think the reason is that it’s possible to have situations where the type cannot be known at compile time. Since `select type` seems a bit verbose, and since it has some run time cost, is it fair to say that one should avoid class variables and use types instead unless their flexibility is needed?

```auto
module m
implicit none
type :: a
  integer :: i
end type
!
type, extends(a) :: b
  integer :: j
end type
!
contains
subroutine set(c)
! c can be either type(a) or type(b) upon return
class(a), intent(out), allocatable :: c
real :: x
call random_number(x)
if (x > 0.5) then
   c = a(i=3)
else
   c = b(i=3,j=4)
end if
end subroutine set
end module m

program poly
use m
implicit none
class(a), allocatable :: c, d
type(b) :: z
integer :: k
z = b(i=3,j=4)
print*,z%i,z%j
c = a(i=3)
! print*,c%i,c%j ! I understand why this does not work.
c = b(i=3,j=4)
! Although c has type b here, sometimes the type of c is known only at run-time. 
! print*,c%i,c%j ! Error: 'j' at (1) is not a member of the 'a' structure
select type (c)
   type is (b)
      print*,c%i,c%j ! works within select type
end select
do k=1,10
   call set(d) ! At compile time, type of d is unknown.
   print*,same_type_as(c,d)
end do
end program poly

```

---

<div class="post-metadata">

**Author:** ![everythingfunctional](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/everythingfunctional/32/176_2.png) [@everythingfunctional](https://fortran-lang.discourse.group/u/everythingfunctional)\
**Post date:** [January 24, 2022, 7:05pm UTC](https://fortran-lang.discourse.group/t/understanding-the-need-for-class-variables-and-select-type/2645/2 "2022-01-24T19:05:26Z")

</div>

My recommendations are that one should use `type`, or carefully design `deferred` type bound procedures defined by the type that one will declare variables of `class` of such that any `select type`s will be unnecessary.

---

<div class="post-metadata">

**Author:** ![rwmsu](https://avatars.discourse-cdn.com/v4/letter/r/48db29/32.png) [@rwmsu](https://fortran-lang.discourse.group/u/rwmsu)\
**Post date:** [January 24, 2022, 8:50pm UTC](https://fortran-lang.discourse.group/t/understanding-the-need-for-class-variables-and-select-type/2645/3 "2022-01-24T20:50:51Z")

</div>

@beliavsky, for a good introduction to OOP in Fortran I highly recommend the chapter on Object-Oriented programming in Stephen Chapman’, “Fortran for Scientists and Engineers (4th edition”, McGraw-Hill. When I first starting trying to learn OOP I struggled with a lot of the concepts because they were usually described in languages (C++, Smalltalk, etc) that I had no experience with. Just being able to see the concepts expressed in Fortran was a big help, plus I think Chapman’s discussion of OOP is one of the clearest and easiest to understand that I’ve seen for any language. Also, this book appears to have undergone a large drop in price lately. It was around $335 dollars at one time. Amazon currently lists the paperback version at $127 and the eBook at $67

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [January 25, 2022, 3:50pm UTC](https://fortran-lang.discourse.group/t/understanding-the-need-for-class-variables-and-select-type/2645/4 "2022-01-25T15:50:38Z")

</div>

> [@everythingfunctional](#):
>
> My recommendations are that one should use `type`, or carefully design `deferred` type bound procedures defined by the type that one will declare variables of `class` of such that any `select type`s will be unnecessary.

Reading Metcalf/Reid/Cohen and Chapman, I was able to write my first `abstract` type with a `deferred` procedure. As said above, with abstract types one can get run-time polymorphism without the need for `select type`.

```auto
module person_mod
implicit none
!
type, abstract, public :: person
  character (len=20) :: name
  contains
    procedure(display_p), deferred :: display 
end type person
!
abstract interface
   subroutine display_p(this)
   import person
   implicit none
   class(person), intent(in) :: this
   end subroutine display_p
end interface
!
type, extends(person) :: worker
  integer :: pay
  contains
    procedure :: display => display_worker
end type
!
type, extends(person) :: student
  integer :: grade
  contains
    procedure :: display => display_student
end type
character (len=*), parameter :: fmt_d = "(3a8,i8)"
!
contains
!
subroutine display_worker(this)
class(worker), intent(in) :: this
print fmt_d,"name = ",this%name," pay =",this%pay
end subroutine display_worker
!
subroutine display_student(this)
class(student), intent(in) :: this
print fmt_d,"name = ",this%name," grade =",this%grade
end subroutine display_student
!
end module person_mod
!
program test_person
use person_mod, only: person, worker, student
implicit none
type(worker) :: w
type(student) :: s
class(person), allocatable :: p
w = worker("Ed",50000)
s = student("Ann",11)
call w%display()
p = w
call p%display()
call s%display()
p = s ! p has new type
call p%display()
end program test_person

```

Output:

```auto
 name = Ed pay = 50000
 name = Ed pay = 50000
 name = Ann grade = 11
 name = Ann grade = 11

```
