Search code examples
fortranprivate

How to pass a private variant value into declaration when overide new functions


For instance, I have a definition of type A in moduleA:

 Module moduleA
   implicit none 
   type A
        private 
        integer::N
   contains 
        ... 
        procedure,pass::f=>f1
   endtype
   private::f1
   contains
   real function f1(self,x)
        real::x(self%n)
   end function
   ...
 end Module

Then I found I meet a trouble when I override function f in other modules since I can not get the value of N. Even though I can have a method to get that, it seems that something like real :: x(self%get()) is impossible in the declaration. I want to keep the rule of "private" in OPP. So what choices can I have?


Solution

  • You cannot do that. At least in the way you describe. It would be better to see an example of the overriding to suggest other options.

    The private attribute works differently in Fortran and therefore you should not directly use rules from other languages that use OOP where private means something different.

    In Fortran private is about the local module, in C++ it is about the derived classes. This is very different and you cannot use the C++ (or Java, etc.) rules for private in Fortran when private in fact means something else.


    To be clear, I assume you wanted this kind of overriding:

       real function f2(self,x)
            class(B) :: self
            real::x(self%get())
       end function
    

    You than get these messages:

    private.f90(15): error #8497: Illegal use of a procedure name in an expression, possibly a function call missing parenthesis.   [GET]
            real::x(self%get())
    ---------------------^
    

    or

            real::x(self%get())
                    1
    Error: 'get' at (1) should be a FUNCTION
    

    So the compilers will not accept a type-bound procedure in the declaration. They would accept an ordinary procedure.


    This compiles in gfortran, but not in Intel Fortran. But get() must be public, which you might not want:

       real function f1(self,x)
            class(A) :: self
            real::x(get(self))
       end function
    
       real function f2(self,x)
            class(B) :: self
            real::x(get(self))
       end function
    

    In ifort I get

    error #8383: The dummy arguments of an overriding and overridden binding that correspond by position must have the same characteristics, except for the type of the passed object dummy arguments.
    

    which is weird.