Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Function returning a class instance - how to ?

776 views
Skip to first unread message

GianLuigi Piacentini

unread,
Sep 21, 2019, 8:40:27 PM9/21/19
to
Hi all,
I have an old module, more or less Fortran95, defining a type (say
my_type) and containing some functions and some subroutines acting on
my_type and, in case of the functions, returning instances of my_type.

I would like to adapt it to every type resulting from extension to
my_type (say type, extends(my_type) :: my_extended_type), so I plan to
replace type(my_type) with class(my_type) in the dummy argument
declarations.
So far it seems ok, but what about the functions resulting in my_type ?
To my understanding, they cannot be class(my_type), since only dummy
arguments are permitted to be class.
To be clearer, I would like to have
function my_function (a) result(b)
class(my_type), intent(in):: a
class(my_type) :: b ! but this is forbidden

Any suggestion to achieve such effect ?

Thanks in advance

Gigi

paul.rich...@gmail.com

unread,
Sep 22, 2019, 3:21:56 AM9/22/19
to
Gianluigi,

The class entities that are not dummy arguments must be declared to be allocatable or pointers. This requirement comes about because the dynamic type of your version of declaration is not determined.

Thus:

class(my_type), intent(in) :: a
class(my_type), allocatable :: b
....
allocate(b, source = my_extended_type (..args..))
or allocate(b, source = a)

Regards

Paul

GianLuigi Piacentini

unread,
Sep 23, 2019, 2:01:48 PM9/23/19
to
> Gianluigi,
>
> The class entities that are not dummy arguments must be declared to be
> allocatable or pointers. This requirement comes about because the
> dynamic type of your version of declaration is not determined.
>
> Thus:
>
> class(my_type), intent(in) :: a class(my_type), allocatable :: b
> ....
> allocate(b, source = my_extended_type (..args..))
> or allocate(b, source = a)
>
> Regards
>
> Paul

Thanks,
sorry for replying late.

The situation is as follows:

module my_type_old

implicit none
private
type, public :: my_type
private
real :: r
end type my_type

interface operator(+)
module procedure sum_my_types
end interface
public :: operator(+)

contains

function sum_my_types (t1, t2) result (t_sum)
type(my_type), intent(in) :: t1, t2
type(my_type) :: t_sum

t_sum%r = t1%r + t2%r

end function sum_my_types

end module my_type_old

module extended_type

implicit none
private

type, extends(my_type), public :: new_type
private
integer :: i
end type new_type

contains
! access procedures to i snipped
end module extended_type

Now I would like that new_type inherited the sum, as defined in module
my_type_old, so I modify function sum_my_types as
class(my_type), intent(in) :: t1, t2
but I cannot write
type (new_type) :: n1, n2, n_sum
n_sum = n1 + n1
intending that the operation will compute n_sum%r as n1%r + n2%r, leaving
the other components of n_sum untouched, because the function mechanism
does not act this way.
I could write a subroutine, or making the type internals public
new_type%my_type_old = n1%my_type_old + n2%my_type_old

Does any other solution exist ?

Thanks in advance
Gigi

ga...@u.washington.edu

unread,
Sep 23, 2019, 7:00:12 PM9/23/19
to
On Monday, September 23, 2019 at 11:01:48 AM UTC-7, GianLuigi Piacentini wrote:

(snip)

> Now I would like that new_type inherited the sum, as defined in module
> my_type_old, so I modify function sum_my_types as
> class(my_type), intent(in) :: t1, t2

> but I cannot write
> type (new_type) :: n1, n2, n_sum
> n_sum = n1 + n1

> intending that the operation will compute n_sum%r as n1%r + n2%r, leaving
> the other components of n_sum untouched, because the function mechanism
> does not act this way.

> I could write a subroutine, or making the type internals public
> new_type%my_type_old = n1%my_type_old + n2%my_type_old

> Does any other solution exist ?

This reminds me of the recent question about functions returning
allocatables. As you say, the function mechanism doesn't work
that way.

The answer to the allocatable question is to use a subroutine,
and that seems the answer here, too.

Functions return a value, which is then used by the caller,
usually in an expression, but sometimes just as a value in an
assignment.


Otherwise, I am not sure what you mean about making
things public.

new_type%my_type_old = n1%my_type_old + n2%my_type_old

does not seem to require anything public. For example,
it isn't directly referencing r in the superclass.

I believe the Java way is to directly call the method in
the superclass, though.

FortranFan

unread,
Sep 23, 2019, 8:18:09 PM9/23/19
to
On Monday, September 23, 2019 at 2:01:48 PM UTC-4, GianLuigi Piacentini wrote:

> ..
> Does any other solution exist ?
> ..

I don't know about "other solution" but there have been quite a few discussions about the difficulties and gotchas with defined operations (and assignment) and type extension on this forum, particularly with compiler support and bugs when it comes to polymorphism and ABSTRACT types and type-bound procedures, all of which have been exacerbated by profound deficiencies in both the language of the standard itself as well as vision about how best to serve the practitioners of Fortran.

And even though it's not stated as such in the standard, an argument can be made the indicated approach, a de facto *canonical* one, for the kind of need expressed by OP is to extend the generic interfaces and effectively daisy chain the defined operations like so:

--- begin example ---
module my_type_old

implicit none
private
type, public :: my_type
private
real :: r = 1.0
end type my_type

interface operator(+)
module procedure sum_my_types
end interface
public :: operator(+)

interface output
module procedure out_my_type
end interface
public :: output

contains

function sum_my_types (t1, t2) result (t_sum)
type(my_type), intent(in) :: t1, t2
type(my_type) :: t_sum

t_sum%r = t1%r + t2%r

end function sum_my_types

subroutine out_my_type( t )
type(my_type), intent(in) :: t
print *, "t%r = ", t%r
end subroutine

end module my_type_old

module extended_type

use my_type_old

implicit none
private

type, extends(my_type), public :: new_type
private
integer :: i = 21
end type new_type

interface operator(+)
module procedure sum_new_types
end interface
public :: operator(+)

interface output
module procedure out_new_type
end interface
public :: output

contains

function sum_new_types (t1, t2) result (t_sum)
type(new_type), intent(in) :: t1, t2
type(new_type) :: t_sum

t_sum%my_type = t1%my_type + t2%my_type
t_sum%i = t1%i + t2%i

end function sum_new_types

subroutine out_new_type( t )
type(new_type), intent(in) :: t
call output( t%my_type )
print *, "t%i = ", t%i
end subroutine

end module extended_type

program p
blk1: block
use my_type_old
type(my_type) :: foo, bar
print *, "Block 1"
call output( foo+bar )
print *, "Expected is r = 2.0"
end block blk1
print *
blk2: block
use extended_type
type(new_type) :: foo, bar
print *, "Block 2"
call output( foo+bar )
print *, "Expected is r = 2.0"
print *, "and i = 42"
end block blk2
end program
--- end example ---

Upon execution, the expected program output is

Block 1
t%r = 2.00000000
Expected is r = 2.0

Block 2
t%r = 2.00000000
t%i = 42
Expected is r = 2.0
and i = 42

GianLuigi Piacentini

unread,
Sep 24, 2019, 1:36:13 PM9/24/19
to
FortranFan <pare...@gmail.com>
ga...@u.washington.edu

Thanks to both !!!



Fortranfan,

your solution, is probably the way to go, to save the possibility to use
operators. I'm just wandering what's the difference, in practice, with
respect to the old (say Fortran95) way to do this same thing - having
explicitly a my_type instance in new_type. Seem to me type extension
does not have any advantage in this case ...
I will anyway save your example and peruse it.

Many thanks
Gigi

ga...@u.washington.edu

unread,
Sep 24, 2019, 7:15:05 PM9/24/19
to
On Tuesday, September 24, 2019 at 10:36:13 AM UTC-7, GianLuigi Piacentini wrote:

(snip)

> your solution, is probably the way to go, to save the possibility to use
> operators. I'm just wandering what's the difference, in practice, with
> respect to the old (say Fortran95) way to do this same thing - having
> explicitly a my_type instance in new_type. Seem to me type extension
> does not have any advantage in this case ...
> I will anyway save your example and peruse it.

C programmers also use structure containing structures, and often
make the assumption that one will map to one with all the members.

But also, when done that way, you have to put in all the intermediate
qualifications.

A PL/I feature, I believe inherited from COBOL, of partial
qualification. You can reference a structure member leaving out
any qualifiers not needed to make it unambiguous.

COBOL only allows one dimensional arrays, which in the case of
structures means one dimension for each structure level.
(I don't know if they have changed this over the years.)

A structure member might be:

A(I).B(J).C(K).D(L).X

but you can reference it as:

X(I,J,K,L) using partial qualification, and also the ability
to move subscripts around.

But classes and inheritance are part of object-oriented programming,
so that might be a reason.

FortranFan

unread,
Sep 24, 2019, 10:59:44 PM9/24/19
to
On Tuesday, September 24, 2019 at 1:36:13 PM UTC-4, GianLuigi Piacentini wrote:

> ..
> Fortranfan,
>
> your solution, is probably the way to go, to save the possibility to use
> operators. I'm just wandering what's the difference, in practice, with
> respect to the old (say Fortran95) way to do this same thing - having
> explicitly a my_type instance in new_type. Seem to me type extension
> does not have any advantage in this case ...
> I will anyway save your example and peruse it.
>
> Many thanks
> Gigi


Re: "Seem to me type extension does not have any advantage in this case," as shown above with a minimal example with 2 'classes' that have no meaningful data and no methods which do anything interesting on the data, yes there's really no benefit with type extension. One has to do object-oriented analysis and design (OOA and OOD) and really find good reasons to employ inheritance and only then will the benefits with type extension become obvious.

Note now, should one have sufficient rationale to use 'class' inheritance and want to pursue Java (or C++ with class methods, or C#/Visual Basic) style coding with *type-bound procedures* (TBPs), here's an alternative you may want to review: notice the aspects about extension of the generic interface with the defined operator (+) and procedure overriding with 'output':

--- begin example 2 ---
module my_type_old

implicit none
private
type, public :: my_type
private
real :: r = 1.0
contains
private !<-- default, typically a good OO coding practice
procedure, pass(lhs) :: sum_my_types
procedure, pass(this), public :: output => output_my_types
generic, public :: operator(+) => sum_my_types
end type my_type

contains

function sum_my_types (lhs, rhs) result (t_sum)

! Argument list
class(my_type), intent(in) :: lhs
type(my_type), intent(in) :: rhs
type(my_type) :: t_sum

t_sum%r = lhs%r + rhs%r

return

end function sum_my_types

subroutine output_my_types( this )
class(my_type), intent(in) :: this
print *, "t%r = ", this%r
end subroutine

end module my_type_old

module extended_type

use my_type_old

implicit none
private

type, extends(my_type), public :: new_type
private
integer :: i = 21
contains
private !<-- default, a good OO coding practice
procedure, pass(lhs) :: sum_new_types
procedure, pass(this), public :: output => output_new_types !<-- Procedure override
generic, public :: operator(+) => sum_new_types !<-- extend the generic interface for the defined operation
end type new_type

contains

function sum_new_types (lhs, rhs) result (t_sum)

! Argument list
class(new_type), intent(in) :: lhs
type(new_type), intent(in) :: rhs
type(new_type) :: t_sum

t_sum%my_type = lhs%my_type + rhs%my_type
t_sum%i = lhs%i + rhs%i

return

end function sum_new_types

subroutine output_new_types( this )
class(new_type), intent(in) :: this
call this%my_type%output()
print *, "t%i = ", this%i
end subroutine

end module extended_type

program p
blk1: block
use my_type_old, only : my_type
type(my_type) :: foo, bar
type(my_type) :: foobar
print *, "Block 1"
foobar = foo + bar
call foobar%output()
print *, "Expected is r = 2.0"
end block blk1
print *
blk2: block
use extended_type, only : new_type
type(new_type) :: foo, bar
type(new_type) :: foobar
print *, "Block 2"
foobar = foo + bar
call foobar%output()
print *, "Expected is r = 2.0"
print *, "and i = 42"
end block blk2
print *
blk3: block
use my_type_old, only : my_type
use extended_type, only : new_type
type(new_type) :: foo, bar
class(my_type), allocatable :: foobar
print *, "Block 3"
!foobar = foo + bar !<-- No allocate on assignment with TBP :-(
allocate( new_type :: foobar )
foobar = foo + bar
call foobar%output()
print *, "Expected is r = 2.0"
print *, "and i = 42"
end block blk3
print *
blk4: block
use my_type_old, only : my_type
class(my_type), allocatable :: foo, bar
class(my_type), allocatable :: foobar
print *, "Block 4"
allocate( my_type :: foo, bar, foobar )
foobar = foo + bar !<-- No allocate on assignment with TBP :-(
call foobar%output()
print *, "Expected is r = 2.0"
end block blk4
print *
blk5: block
use my_type_old, only : my_type
use extended_type, only : new_type
class(my_type), allocatable :: foo, bar
class(my_type), allocatable :: foobar
print *, "Block 5"
allocate( new_type :: foo, bar, foobar )
foobar = foo + bar !<-- No allocate on assignment with TBP :-(
call foobar%output()
print *, "Expected is r = 2.0"
print *, "and i = 42"
end block blk5
print *
blk6: block
use my_type_old, only : my_type
use extended_type, only : new_type
class(my_type), allocatable :: foo, bar
type(new_type) :: foobar
print *, "Block 6"
allocate( new_type :: foo, bar )
select type ( foo )
type is ( new_type )
select type ( bar )
type is ( new_type )
foobar = foo + bar !<-- Assignment inside verbose 'casting'
end select
end select
call foobar%output()
print *, "Expected is r = 2.0"
print *, "and i = 42"
end block blk6
print *
blk7: block
use extended_type, only : new_type
type(new_type) :: foo, bar
print *, "Block 7"
associate ( foobar => foo+bar ) !<-- not supported by gfortran
call foobar%output()
print *, "Expected is r = 2.0"
print *, "and i = 42"
end associate
end block blk7
end program
--- end example 2 ---

Upon execution with Intel Fortran, the output is as I expect:
Block 1
t%r = 2.000000
Expected is r = 2.0

Block 2
t%r = 2.000000
t%i = 42
Expected is r = 2.0
and i = 42

Block 3
t%r = 2.000000
t%i = 42
Expected is r = 2.0
and i = 42

Block 4
t%r = 2.000000
Expected is r = 2.0

Block 5
t%r = 2.000000
Expected is r = 2.0
and i = 42

Block 6
t%r = 2.000000
t%i = 42
Expected is r = 2.0
and i = 42

Block 7
t%r = 2.000000
t%i = 42
Expected is r = 2.0
and i = 42

whereas gfortran does not support the ASSOCIATE construct in "Block 7" involving the defined operation; my hunch is that is a gfortran bug, though I'm not completely sure about it, I will need to review the standard more closely.

GianLuigi Piacentini

unread,
Sep 25, 2019, 1:32:43 PM9/25/19
to
On Tue, 24 Sep 2019 19:59:41 -0700, FortranFan wrote:

> On Tuesday, September 24, 2019 at 1:36:13 PM UTC-4, GianLuigi Piacentini
> wrote:
>
>> ..
>> Fortranfan,
>>
>> your solution, is probably the way to go, to save the possibility to
>> use operators. I'm just wandering what's the difference, in practice,
>> with respect to the old (say Fortran95) way to do this same thing -
>> having explicitly a my_type instance in new_type. Seem to me type
>> extension does not have any advantage in this case ...
>> I will anyway save your example and peruse it.
>>
>> Many thanks Gigi
>
>
> Re: "Seem to me type extension does not have any advantage in this
> case," as shown above with a minimal example with 2 'classes' that have
> no meaningful data and no methods which do anything interesting on the
> data, yes there's really no benefit with type extension. One has to do
> object-oriented analysis and design (OOA and OOD) and really find good
> reasons to employ inheritance and only then will the benefits with type
> extension become obvious.

Unfortunately I'm almost totally ignorant of OOA and OOD (and I'm too
lazy and to old to learn it - after all now that I'm retired programming
is an hobby).
At the moment I'm concerned with the "my_type" part. It will be a 1000+
line module of operations on my_type, to be put in an object library.
I simply liked to let things open for future development, if needed.
At this moment, I see only the extended components (integer :: i) as
perhaps several auxiliary data (a name identifying the instance, and by
which the instance may be searched, an usage counter - anyway all stuff
that are completely unrelated to the operators defined over my_type.
>
> Note now, should one have sufficient rationale to use 'class'
> inheritance and want to pursue Java (or C++ with class methods, or
> C#/Visual Basic) style coding with *type-bound procedures* (TBPs),
> here's an alternative you may want to review: notice the aspects about
> extension of the generic interface with the defined operator (+) and
> procedure overriding with 'output':
>
> --- begin example 2 ---

Thanks for this, I will save it for study.

Gigi

Ev. Drikos

unread,
Sep 25, 2019, 11:21:26 PM9/25/19
to
On 25/09/2019 5:59 AM, FortranFan wrote:
> ...
>

@FortranFan

When you posted your first example, I was wondering why you opted for an
interface for the "output" function instead of a type method (TBP) that
seemed to me the obvious way, but the example was already two good for
questions. Your newer example exposes various compiler specific issues.

> --- begin example 2 ---
> module my_type_old
> ...
> blk3: block
> use my_type_old, only : my_type
> use extended_type, only : new_type
> type(new_type) :: foo, bar
> class(my_type), allocatable :: foobar
> print *, "Block 3"
> !foobar = foo + bar !<-- No allocate on assignment with TBP :-(

Not sure whether the archaic compiler I use is buggy and needs explicit
interface assignments or it's a feature added by a newer draft. Would
the extra code attached at the end of this message spoil the example?

> whereas gfortran does not support the ASSOCIATE construct in "Block 7" involving the defined operation; my hunch is that is a gfortran bug, though I'm not completely sure about it, I will need to review the standard more closely.
>

Also, I hope we'll see some response about this issue, where
gfortran-8 needs a temporary.


Ev. Drikos

--------------------------------------------------------------------
------------------------ in module my_type_old ---------------------
interface assignment(=)

module procedure :: assign_base_t !allocatable lhs

end interface assignment(=)
public :: assignment(=)
subroutine assign_base_t(to, from)

class(my_type), allocatable, intent(inout) :: to
class(my_type), intent(in) :: from

if (allocated(to)) then
deallocate(to)
end if

allocate(to,source=from)

end subroutine
--------------------------------------------------------------------
------------------------ in module extended_type -------------------
interface assignment(=)

module procedure :: assign_extended_t !allocatable lhs

end interface assignment(=)
subroutine assign_extended_t(to, from)

type(new_type), allocatable, intent(inout) :: to
class(new_type), intent(in) :: from

print *, "Is this ever called?"

if (allocated(to)) then
deallocate(to)
end if

allocate(to,source=from)


end subroutine
--------------------------------------------------------------------

Ev. Drikos

unread,
Sep 29, 2019, 11:33:17 PM9/29/19
to
On 25/09/2019 5:59 AM, FortranFan wrote:
> ...
>
> Upon execution with Intel Fortran, the output is as I expect:
> ...
>
> Block 5
> t%r = 2.000000
> Expected is r = 2.0
> and i = 42
>
> ...
>
> whereas gfortran ...

... prints exactly the same results (several versions). But I was
expecting to see the output printed by the dynamic type, not by
the declared type. Yet, the "sum" returned has the base type "my_type".

Once two compilers from different vendors agree, is this perhaps a typo?

Ev. Drikos


FortranFan

unread,
Sep 30, 2019, 5:20:56 PM9/30/19
to
> ..


In my first response to OP (https://groups.google.com/d/msg/comp.lang.fortran/EtGmIRqvF2E/oeZ9LiJXCAAJ), I mentioned 'gotchas' and this is one of them. I'm glad @Ev. Drikos noticed it and brought it up.

I believe the code as shown in https://groups.google.com/d/msg/comp.lang.fortran/EtGmIRqvF2E/ITrDC4iuCAAJ is conformant and the responses from the 2 compilers are as expected. Note the Fortran states in section 10.1.9.2, "If the function reference is generic (15.4.3.2, 16.7) then its type, type parameters, and shape are those of the specific function referenced, which is determined by the declared types, type parameters, and ranks of its actual arguments as specified in 15.5.5.2." Accordingly, when the instruction 'foobar = foo + bar' is executed, the defined operation as defined by the generic gets determined by the 'sum_my_types' function reference even though the 'dynamic types' of foo and bar are 'new_type'. Following the function result which is of type 'my_type', the allocation on assignment comes into play and the object 'foobar' gets reallocated as an object of 'my_type'.

As to @Ev. Drikos' comment "I was expecting to see the output printed by the dynamic type, not by the declared type," in order of this to occur I believe the code has to be like so:

--- begin snippet ---
..
allocate( new_type :: foo, bar, foobar )
select type ( foo )
type is ( new_type )
select type ( bar )
type is ( new_type )
foobar = foo + bar !<-- Forces the function reference to 'sum_new_types'
end select
end select
call foobar%output()
..
--- end snippet ---

This can all be terribly confusing to hobbyist coders as well as compiler developers who expertise is often in other languages (e.g., C++). Hence my first example without polymorphism which keeps things simple.


ga...@u.washington.edu

unread,
Sep 30, 2019, 6:46:56 PM9/30/19
to
On Monday, September 30, 2019 at 2:20:56 PM UTC-7, FortranFan wrote:

(snip)
> --- begin snippet ---
> ..
> allocate( new_type :: foo, bar, foobar )
> select type ( foo )
> type is ( new_type )
> select type ( bar )
> type is ( new_type )
> foobar = foo + bar !<-- Forces the function reference to 'sum_new_types'
> end select
> end select
> call foobar%output()
> ..
> --- end snippet ---
>
> This can all be terribly confusing to hobbyist coders as
> well as compiler developers who expertise is often in other
> languages (e.g., C++).
> Hence my first example without polymorphism which keeps things simple.

Trying to think about how this might work in Java, but with polymorphism,
and the original my_type and new_type, I think you can:

my_type foo, bar, foobar;
foo = new new_type();
bar = new net_type();

foobar = foo.add(bar); // no operator override in Java

Even though the variable foo is my_type, at run time Java figures
out that it is actually new_type, and calls the new_type add method.

There must be an add method in my_type, or it will fail at
compile time. If there is no add in new_type, then the my_type one
still gets called. (Reference) variables can always hold a value
of the subclass of their class, but not a superclass.

Object is the superclass of all classes, so can hold a reference
to any class.

Object o = foo;
bar = (my_class) o;

The assignment to bar casts to (my_class) which will fail unless o
is (my_class) or a subclass of (my_class).






Ev. Drikos

unread,
Sep 30, 2019, 7:25:07 PM9/30/19
to
On 01/10/2019 1:46 AM, ga...@u.washington.edu wrote:
> ...
>>
> Trying to think about how this might work in Java, but with polymorphism,
> and the original my_type and new_type, I think you can:
>
> my_type foo, bar, foobar;
> foo = new new_type();
> bar = new net_type();
>
> foobar = foo.add(bar); // no operator override in Java
>
> Even though the variable foo is my_type, at run time Java figures
> out that it is actually new_type, and calls the new_type add method.
>
> ...
>

Exactly and this is the essence of specialization!

BTW, I think that one can't alter the visibility of the method "add" in
a sub-class.



ga...@u.washington.edu

unread,
Sep 30, 2019, 9:29:01 PM9/30/19
to
On Monday, September 30, 2019 at 4:25:07 PM UTC-7, Ev. Drikos wrote:

(snip, I wrote)

> > Trying to think about how this might work in Java, but with polymorphism,
> > and the original my_type and new_type, I think you can:

> > my_type foo, bar, foobar;
> > foo = new new_type();
> > bar = new new_type();

(fix spelling error above)

> > foobar = foo.add(bar); // no operator override in Java

> > Even though the variable foo is my_type, at run time Java figures
> > out that it is actually new_type, and calls the new_type add method.


> Exactly and this is the essence of specialization!

> BTW, I think that one can't alter the visibility of the
> method "add" in a sub-class.

I hadn't thought about that.

I would guess that you could make it less restrictive,
but not more restrictive, but that is a guess.

As above, if my_type doesn't have add, or if as you note, it
isn't visible, then it will fail to compile.

Parts of the superclass that aren't visible shouldn't affect
what the subclass can do.

Ev. Drikos

unread,
Oct 1, 2019, 9:05:37 AM10/1/19
to
On 01/10/2019 4:28 AM, ga...@u.washington.edu wrote:
> ...
>
>> BTW, I think that one can't alter the visibility of the
>> method "add" in a sub-class.
>
> I hadn't thought about that.
>
> I would guess that you could make it less restrictive,
> but not more restrictive, but that is a guess.
>

Indeed, the exact error message issued by JDK 8 is:
"Cannot reduce the visibility of the inherited method from ..."

My comment here is that if a method in a super-class is private
and in a sub-class public, then any call would need type casting.
But within a package the method of a super-class can be protected.

Ev. Drikos

unread,
Oct 1, 2019, 9:08:38 AM10/1/19
to
On 01/10/2019 4:05 PM, Ev. Drikos wrote:
> On 01/10/2019 4:28 AM, ga...@u.washington.edu wrote:
>> ...
>>
>>> BTW, I think that one can't alter the visibility of the
>>> method "add" in a sub-class.
>>
>> I hadn't thought about that.
>>
>> I would guess that you could make it less restrictive,
>> but not more restrictive, but that is a guess.
>>
>
> Indeed, the exact error message issued by JDK 8 is:
> "Cannot reduce the visibility of the inherited method from ..."
>
> My comment here is that if a method in a super-class is private
> and in a sub-class public, then any call would need type casting.
> But within a package the method of a super-class can be protected
and at the same time directly accessible by other package classes.

PS: sorry for the partial statement.

paul.rich...@gmail.com

unread,
Oct 2, 2019, 8:37:01 PM10/2/19
to

> whereas gfortran does not support the ASSOCIATE construct in "Block 7" involving the defined operation; my hunch is that is a gfortran bug, though I'm not completely sure about it, I will need to review the standard more closely.

This is now PR91978. It is indeed a bug, which comes about because the type and kind of 'foobar' is not being determined during parsing.

Thanks

Paul
0 new messages