Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Polymorphic Pointers

dundar11
Beginner
1,668 Views

I am trying to use pointers to create links between objects. Using Fortran and here is the code piece:

 module base_pars_module
   type,abstract,public :: base_pars
   end type
 end module 
 module test_parameters_module
   use base_pars_module
   type, extends(base_pars) :: test_pars
     contains 
     procedure :: whoami
   end type
   contains
   function whoami(this) result(iostat)
     class( test_pars) :: this
     write(*,*) 'i am a derived type child of base_pars'
   end type
 end module
 module base_mask_module
   use base_pars module
     type, abstract , public :: base_mask
     class(base_pars),pointer :: parameters
   end type
end module
module test_mask_module
  use base_mask_module
  implicit none
  type, extends(base_mask) :: test_mask
  end type
end module
program driver
type(test_pars) , target :: par_Test
type(test_mask) :: mask_test
  iostat= par_test%whoami()
  mask_test%parameters=>par_test
  iostat=mask_test%parameters%whoami()
end program

parameters at base_mask_module is a pointer with base_pars class. I would like to use this pointer to refer par_test object which is test_pars type that extends base_pars type. So the pointer and the target has the same class. But when I compile this it gives an error:

 driver.f90:17.37:

iostat=mask_test%parameters%whoami()
                                  1
Error: 'whoami' at (1) is not a member of the 'base_pars' structure

Is it a bug or am i doing something wrong?

0 Kudos
7 Replies
FortranFan
Honored Contributor III
1,668 Views

Look into "SELECT TYPE" construct: you need it to unmask the polymorphic object and invoke the methods associated with it.

0 Kudos
IanH
Honored Contributor III
1,668 Views

Your question has already been answered by others at http://stackoverflow.com/questions/31220961/fortran-polymorphism-in-pointers

The error message is valid and a reasonable summary of the problem with the code.  `mask_test%parameters` is of type `base_pars`, and that type does not have a binding `whoami`.  The presence of a binding of that name in types that are extensions of `base_pars` is not relevant - in a statically typed language, such as Fortran (and many others), the available set of bindings and components are determined by the declared type of an object, not its dynamic type. 

0 Kudos
dundar11
Beginner
1,668 Views

I know that answers in the StackoverFlow but wanted to port the discussion here.

My problem in fact is this. I want to create objects from two different abstract classes.

Lets say base_a and base_b

And I want to create objects from classes  class_a which is child of base_a and class_b child of base_b.

And , I want to establish a connection between child_a and child_b in terms of pointers at the abstract type definition while I am defining base_a and base_b. I want a pointer which points from base_a to any objects which inherits base_b. 

I think this is not possible with fortran. If it is I don't know how. I discussed this with a computer engineer, expert in Java. He says it is quite possible to do this with java. As far as I understand, pointers in Fortran are not as polymorphic as pointers of other languages.

So is there any work-around for this?

 

0 Kudos
IanH
Honored Contributor III
1,668 Views

In Fortran, a polymorphic pointer can point at any object that is of a type that is an extension of the type of the pointer (i.e. the type of the pointer and any types that ultimate EXTEND the type of the pointer).  This is exactly what you do in the line before the line that incurs an error message from the compiler.

The error above does not arise because you cannot point the polymorphic pointer at an object - it arises because the type of the pointer is that of the abstract parent type, and that abstract parent type does not have the member that you request.

I am not a java programmer (which is an understatement), but here is the naive transliteration of your example into java.  It fails with a similar error to the Fortran program, for similar reasons.  If I change the type of the member reference to be that of the `test_pars` extension - the error message goes away - as it would if you did the same in Fortran.

Perhaps you can discuss this example with your java expert.  If their response involves using a type cast, to downcast the `mask_test.parameters` reference to a base_pars object to be a reference to a test_pars object, then that is equivalent to using SELECT TYPE in Fortran, as others have suggested. 

class ExampleApp
{
  class base_pars
  {
  }
  
  class test_pars extends base_pars
  {
    public int WhoAmI() {
      System.out.println("I am a test_pars - a subclass of base_pars");
      return 0;
    }
  }
  
  class base_mask
  {
     public base_pars parameters;
    /* public test_pars parameters;   */
  }
  
  class test_mask extends base_mask
  {
  }
  
  
  
  
  public static void main(String[] args)
  {
    try {
      ExampleApp obj = new ExampleApp();
      obj.run(args);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  void run(String[] args)
  {
    test_pars par_Test = new test_pars();
    test_mask mask_test = new test_mask();
    
    mask_test.parameters = par_Test;
    int iostat = mask_test.parameters.WhoAmI();
  }
}

 

0 Kudos
FortranFan
Honored Contributor III
1,668 Views

dundar11 wrote:

.. . I discussed this with a computer engineer, expert in Java. He says it is quite possible to do this with java. As far as I understand, pointers in Fortran are not as polymorphic as pointers of other languages. ..

So why don't you ask this Java expert to give you a minimal working example of what you want to do in Java without using type casting?  And why don't you post the Java example here?  We can then offer comments on what is possible with Fortran.  But I'm willing to bet the "expert in Java" has type casting in mind which, as IanH pointed out, is the same as using SELECT TYPE in Fortran.  One may argue there is "syntactic sugar" available in Java with type casting that allows a coder to accomplish the same task in fewer keystrokes compared to, say, Fortran.  But that would be a separate discussion altogether.  

0 Kudos
dundar11
Beginner
1,668 Views

That java part was a misunderstanding between me and my friend. However is it possible to "cast" type of the pointer?

In the initial example

     class(base_pars),pointer :: parameters

Pointer parameters belongs to base_pars class. What if I allocate this pointer at the body of the program:

allocate(test_pars::mask_test%parameters)

and point this to par_Test?

mask_test%parameters=>par_test

and call the function whoami later:

iostat=mask_test%parameters%whoami()

It still gives the compiler error. says whoami does not belong to base_pars class. However I should be able to cast this pointer with test_pars type. If not what is the point of using classes?

0 Kudos
FortranFan
Honored Contributor III
1,668 Views

dundar11 wrote:

That java part was a misunderstanding between me and my friend. However is it possible to "cast" type of the pointer?

In the initial example

     class(base_pars),pointer :: parameters

Pointer parameters belongs to base_pars class. What if I allocate this pointer at the body of the program:

allocate(test_pars::mask_test%parameters)

and point this to par_Test?

mask_test%parameters=>par_test

and call the function whoami later:

iostat=mask_test%parameters%whoami()

It still gives the compiler error. says whoami does not belong to base_pars class. However I should be able to cast this pointer with test_pars type. If not what is the point of using classes?

No, you would still need to use "SELECT TYPE" construct to unmask the polymorphic object.  Or if the base_pars class design is something you have control over, you can redesign it as suggested to you on the StackOverflow forum.

Re: "what is the point of using classes?", you can best answer this question for yourself by (re)reading the books/articles on object-oriented programming applications in Fortran e.g., https://software.intel.com/en-us/blogs/2013/12/30/doctor-fortran-in-its-a-modern-fortran-world and http://www.hindawi.com/journals/sp/2015/942059/

0 Kudos
Reply