I have a scenario where want an array of objects where each element has a different type. Consider the following types
module mymod
implicit none
type, abstract :: Animal
end type
type, extends(Animal) :: Dog
character(len=:), allocatable :: fur_color
end type
type, extends(Animal) :: Fish
integer :: number_of_fins
character(len=:), allocatable :: scale_color
end type
end module
What I want to do is make an array of Animal
, where each element can be either a Dog
or a Fish
. Although, I haven’t managed this. Any array of Animal
must have the same type… For example, I can only do
subroutine test1()
class(Animal), allocatable :: a(:)
allocate(Fish::a(3))
end subroutine
So to accomplish an array of Animal
of different type I must make a container type:
! ...
type :: Container
class(Animal), allocatable :: a
end type
! ...
subroutine test()
class(Container), allocatable :: c(:)
integer :: i
allocate(c(2))
allocate(Fish::c(1)%a)
select type (a => c(1)%a)
class is (Fish)
a%scale_color = "rainbow"
a%number_of_fins = 7
end select
allocate(Dog::c(2)%a)
select type (a => c(2)%a)
class is (Dog)
a%fur_color = "brown"
end select
end subroutine
Question 1: Is this Container
approach the right way to accomplish an array of classes which can each have a different type?
Question 2: Is the syntax
allocate(Dog::c(2)%a)
select type (a => c(2)%a)
class is (Dog)
a%fur_color = "brown"
end select
the only way to “dynamic_cast” (as in c++) a base class to a derived type.
Thanks!