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

Access Issues

Blane_J_
New Contributor I
472 Views

Hi, everyone. I'd like to suggest the following code:

module test1
    implicit none

    type :: a
        integer :: sa
    end type a

end module test1

module test2
    use test1
    implicit none

    type,extends(a) :: b
        private
        integer :: sb
    end type b

end module test2

program main
    use test2
    implicit none

    type(b) :: var
    write(*,*) var%sa    ! sa can be accessed.
    write(*,*) var%sb    ! sb is blocked.
 
end program main

Here comes the question: How can I block sa to be seen from the outside of the type defination module test2 ? In other words how can sa made to be a private variable within type b ? Appriciate any ideas and many thanks.

 

0 Kudos
6 Replies
IanH
Honored Contributor II
472 Views

Given the code you show, make the `sa` component private.  Module `test2` doesn't access it.

If module `test2` does require access, then fortran's accessibility model does not permit the degree of control you request, if you require the types to be defined in different modules.

Conceptually, because type `b` extends type `a`, an object of type `b` is also an object of type `a`.  A characteristic of type `a` is that is has an accessible component named `sa` outside its defining module, and so type `b` has that same characteristic.

If type `a` and type `b` were defined in the same module, the the `sa` component could be made private.

If, conceptually, an object of type `b` should not also be considered an object of type `a`, then consider using composition rather than inheritance - make an object of type `a` a component of type `b`, rather than type `b` extending type `a`.

0 Kudos
Blane_J_
New Contributor I
472 Views

ianh wrote:

Given the code you show, make the `sa` component private.  Module `test2` doesn't access it.

If module `test2` does require access, then fortran's accessibility model does not permit the degree of control you request, if you require the types to be defined in different modules.

Conceptually, because type `b` extends type `a`, an object of type `b` is also an object of type `a`.  A characteristic of type `a` is that is has an accessible component named `sa` outside its defining module, and so type `b` has that same characteristic.

If type `a` and type `b` were defined in the same module, the the `sa` component could be made private.

If, conceptually, an object of type `b` should not also be considered an object of type `a`, then consider using composition rather than inheritance - make an object of type `a` a component of type `b`, rather than type `b` extending type `a`.

Thanks IanH, as you suggested, I made the sa component to be private, but another problem comes up. Assume the change Like:

module test1
    implicit none

    type :: a
        private                 ! <---- Add PRIVATE here.
        integer :: sa
    end type a

end module test1

module test2
    use test1
    implicit none

    type,extends(a) :: b
        private
        integer :: sa          ! <---- Add another sa component here.  !!! INVALID !!!
        integer :: sb
    end type b

end module test2

program main
    use test2
    implicit none

    type(b) :: var
    write(*,*) var%sa
    write(*,*) var%sb
 
end program main

When I add another sa component within type b, the compiler says:

error #8205: A component declared in an extended type cannot have the same name as any accessible component of its parent type.   [SA]

Since sa is private in type a and it is inaccessible outside of test1, why can't I declare another sa in type b ?

The compiler's behavior gives me the thought that type b has an invisible and inaccessible component sa, so you cannot declare the same sa once again, what is mistake here ?

0 Kudos
Mark_Lewy
Valued Contributor I
472 Views

Not that I'd recommend this practice, but it would appear that the Fortran standard should allow you to define a component with the same name as an inaccessible component in the parent type.

In section 4.5.7.2 of the Fortran 2008 and 2015 standards, you have two notes:

NOTE 4.53
Inaccessible components and bindings of the parent type are also inherited, but they remain inaccessible in
the extended type. Inaccessible entities occur if the type being extended is accessed via use association and
has a private entity.

NOTE 4.55
A component or type parameter declared in an extended type shall not have the same name as any accessible
component or type parameter of its parent type.

The fact that a%sa is private by use association would suggest that b%sa ought to be a valid component.

But, even if the declaration of sa in type b compiled, your main program should fail to compile because the components of b are private.

0 Kudos
jimdempseyatthecove
Honored Contributor III
472 Views

As structured in #3, the sa within type a would only be accessible by a contains section within the type declaration. Since there is no type bound procedure, you could construct a unique GUID and tack it onto the type's sa:

integer :: sa_YourNewlyGeneratedGUIDhere

And, if you later add a type bound procedure, you can use the uniquely named sa in the procedure.

Jim Dempsey

0 Kudos
Blane_J_
New Contributor I
472 Views

Mark Lewy wrote:

Not that I'd recommend this practice, but it would appear that the Fortran standard should allow you to define a component with the same name as an inaccessible component in the parent type.

In section 4.5.7.2 of the Fortran 2008 and 2015 standards, you have two notes:

NOTE 4.53
Inaccessible components and bindings of the parent type are also inherited, but they remain inaccessible in
the extended type. Inaccessible entities occur if the type being extended is accessed via use association and
has a private entity.

NOTE 4.55
A component or type parameter declared in an extended type shall not have the same name as any accessible
component or type parameter of its parent type.

The fact that a%sa is private by use association would suggest that b%sa ought to be a valid component.

But, even if the declaration of sa in type b compiled, your main program should fail to compile because the components of b are private.

Thanks Mark, I've read the part you mentioned about the standard and have found that limitation there, so it's all about the standard issue.

0 Kudos
Blane_J_
New Contributor I
472 Views

jimdempseyatthecove wrote:

As structured in #3, the sa within type a would only be accessible by a contains section within the type declaration. Since there is no type bound procedure, you could construct a unique GUID and tack it onto the type's sa:

integer :: sa_YourNewlyGeneratedGUIDhere

And, if you later add a type bound procedure, you can use the uniquely named sa in the procedure.

Jim Dempsey

Thanks Jim, your suggestion should be a way. Since I am willing to use the identical sa name within type b which the standard disallow, I think it should be the time to change the design somehow.

0 Kudos
Reply