- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A FINAL procedure cannot be written for that matter, as it requires the object passed as TYPE, and an ABSTRACT type cannot be instanced.
The reason for wanting a FINAL procedure is to correctly delete some data initialized and used inside. This data is used in some other non-DEFERRED procedures that must be inherited by the children classes.
The non-DEFERRED procedures cannot be moved to any derived class, since the DEFERRED procedure is not defined until the very last class in the hierarchy. Therefore all the chain is ABSTRACT until the last TYPE, implemented by the library user.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
During the finalization process of an object of extended type, the parts of the object that belong to the extension "go-away" first, before the parts belonging to the parent type. If the final procedure for the parent type could take polymorphic objects, then it could invoke deferred bindings that are implemented by the extension type - the procedures associated with those bindings could then work with components that are no longer there. This doesn't make sense - so it is prohibited.
You can either wrap the data up in a separate type that is used as a component of your abstract type - as you have done, or you can wrap it up in a non-abstract parent type of the abstract type.
...
type concrete
integer:: i
contains
FINAL:: destructor_concrete
end type concrete
type, extends(concrete), abstract :: eqObject_abs
contains
procedure(iface_eq_object), pass, deferred :: eq_object
end type eqObject_abs
...
With the above, the characteristics of type `concrete` (its components, bindings etc) become a subset of the characteristics of type `eqObject_abs` (an object of type `eqObject_abs` "is a" object of type `concrete`). If that's philosophically not what you want, then consider retaining your existing composition approach.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Can you encapsulate the abstract type within a defined type that has a FINAL that handles the deletion of the abstract type?
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you Jim.
In that way it doesn't make sense the abstract type because we want to keep the deferred. Maybe you want to say the other way round: encapsulating the data in a type with FINAL and include the encapsulated data in the abstract type. This is what I am doing (see below), but I was wondering if there is any other way to do it. It is annoying not having the possibility of making FINAL in ABSTRACT types.
module test
type concrete
integer:: i
contains
FINAL:: destructor_concrete
end type concrete
type, abstract :: eqObject_abs !< equal unlimited polymorphic type
type(concrete) :: ct
contains
procedure(iface_eq_object), pass, deferred :: eq_object
end type eqObject_abs
abstract interface
subroutine iface_eq_object(this)
import
class(eqobject_abs):: this
end subroutine iface_eq_object
end interface
type, extends(eqobject_abs):: usuario
contains
procedure, pass :: eq_object => usuarioimpl
end type usuario
contains
subroutine destructor_concrete(this)
type(concrete)::this
print *, "i'm called"
end subroutine destructor_concrete
subroutine usuarioimpl(this)
class(usuario):: this
print *, "deferred call"
end subroutine usuarioimpl
subroutine doit()
implicit none
type(usuario):: u
call u%eq_object()
end subroutine doit
end module test
program main
use test
implicit none
call doit()
end program main
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
During the finalization process of an object of extended type, the parts of the object that belong to the extension "go-away" first, before the parts belonging to the parent type. If the final procedure for the parent type could take polymorphic objects, then it could invoke deferred bindings that are implemented by the extension type - the procedures associated with those bindings could then work with components that are no longer there. This doesn't make sense - so it is prohibited.
You can either wrap the data up in a separate type that is used as a component of your abstract type - as you have done, or you can wrap it up in a non-abstract parent type of the abstract type.
...
type concrete
integer:: i
contains
FINAL:: destructor_concrete
end type concrete
type, extends(concrete), abstract :: eqObject_abs
contains
procedure(iface_eq_object), pass, deferred :: eq_object
end type eqObject_abs
...
With the above, the characteristics of type `concrete` (its components, bindings etc) become a subset of the characteristics of type `eqObject_abs` (an object of type `eqObject_abs` "is a" object of type `concrete`). If that's philosophically not what you want, then consider retaining your existing composition approach.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for the alternative, Ian, we haden't thought of this way for organizign the types.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page