Understanding the need for class variables and select type

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.

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:

 name = Ed         pay =   50000
 name = Ed         pay =   50000
 name = Ann      grade =      11
 name = Ann      grade =      11
2 Likes