Full object oriented example with fortran 2003?

Can anyone please give me an example on how is it supposed to be for a simple Fortran 2003 Object oriented layout equivalent to this C++ code:

stefanos-imac:tmp borini$ more Animal.h 
class Animal {
    public:
        Animal(int age);
        ~Animal();
        virtual void speak();
        int getAge();
    private:
        int age;
};

stefanos-imac:tmp borini$ more Animal.cpp 
#include <Animal.h>
#include <iostream>
Animal::Animal(int age) {
    std::cout << "init animal" << age << std::endl;
    this->age = age;
}
Animal::~Animal() {
    std::cout << "dtor animal" << std::endl;
}
void Animal::speak() {
    std::cout << "speak not reimplemented" << std::endl;
}
int Animal::getAge() {
    return this->age;
}
stefanos-imac:tmp borini$ more Cat.h 
#include <Animal.h>
class Cat : public Animal {
    public:
        Cat(int age);
        ~Cat();
        virtual void speak();
};
stefanos-imac:tmp borini$ more Cat.cpp 
#include <Cat.h>
#include <iostream>
Cat::Cat(int age) : Animal(age) {
    std::cout << "init cat" << std::endl;
}
Cat::~Cat() { 
    std::cout << "dtor cat" << std::endl;
}
void Cat::speak() {
    std::cout << "meow" << std::endl;
}
stefanos-imac:tmp borini$ more main.cpp 
#include <iostream>
#include <Cat.h>

int main() {
    Cat c(10);

    std::cout << c.getAge() <<std::endl;
    c.speak();
}

I am having problems with my code, see the following

stefanos-imac:oop borini$ more Animal.f90 
module AnimalModule
   implicit none
   private
   public :: AnimalType

   type :: AnimalType
      private
      integer :: age
   contains
      procedure :: getAge 
      procedure :: speak
      final :: dtor
   end type

   interface AnimalType
      module procedure ctor
   end interface
contains 
   subroutine ctor(self, age)
      type(AnimalType), intent(inout) :: self
      integer :: age
      print *, "Constructor Animal"
      self%age = age
   end subroutine 
   subroutine dtor(self)
      type(AnimalType), intent(inout) :: self
      print *, "Destroying animal"
   end subroutine 

   function getAge(self)
      class(AnimalType), intent(inout) :: self
      integer :: getAge
      getAge = self%age
   end function
   subroutine speak(self)
      class(AnimalType), intent(in) :: self

      print *, "Animal::speak not overridden"
   end subroutine
end

stefanos-imac:oop borini$ more Cat.f90 
module CatModule
   use AnimalModule
   implicit none
   private

   type, extends(AnimalType) :: CatType
      private
   contains
      procedure :: speak 
      final :: dtor
   end type

   interface CatType
      module procedure ctor
   end interface

contains 
   subroutine ctor(self, age)
      type(CatType), intent(inout) :: self
      integer, intent(in) :: age
      print *, "Constructor Cat"
      self%AnimalType = AnimalType(age)
   end subroutine 
   subroutine dtor(self)
      type(CatType), intent(inout) :: self
      print *, "Destroying Cat"
   end subroutine 
   subroutine speak(self)
      class(CatType), intent(in) :: self

      print *, "Meow"
   end subroutine
end

stefanos-imac:oop borini$ ifort Animal.f90 Cat.f90 
Cat.f90(10): error #8341: Final subroutines are not inherited through type extension and cannot be overridden.   [DTOR]
      final :: dtor
---------------^
Cat.f90(22): error #6292: The parent type of this field is use associated with the PRIVATE fields attribute   [AGE]
      self%AnimalType = AnimalType(age)
-----------------------------------^
compilation aborted for Cat.f90 (code 1)
stefanos-imac:oop borini$ 

In particular, it's not clear to me how to initialize the base class, and how to define the destructor for the derived class.

Thanks

Answers


   subroutine ctor(self, age)
      type(CatType), intent(inout) :: self
      integer, intent(in) :: age
      print *, "Constructor Cat"
      self%AnimalType = AnimalType(age)
   end subroutine

This is wrong. CatType has no AnimalType component. It extends the AnimalType type. ctor is a subroutine and you use it as a function. I suggest you, to define constructor (but it will be more just initializing, not allocating) as a function, but subroutine can also be used. You can use the interface block as you did to achieve the same name as the class name, but you have to be consistent and use CALL, if you defined it as a subroutine.

In the constructor of the derived class you could just set the right component, or use the constructor of the base class. Do not forget to write right working user defined assignments for your types then.


Need Your Help

Always check malloc'ed memory?

c architecture system

I often catch myself doing the following (in non-critical components):

How to make change event work for radiobutton for html added with replaceWith

javascript jquery html

I managed to get the change event firing for a radiobutton. However I now needed it to work for html where the radiobutton is added to the markup with replaceWith.