- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I understand the following is not legal:
module foo type :: bar integer :: a=53 end type type, extends(bar) :: rab integer :: a=-33333 !!! Redefine default initialization end type end module
I think this would be quite practical. The only workaround is implementing clumsy constructor wrappers...
Any thoughts?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I prefer not to use default initialization; I use constructors instead. And the Fortran 2003 feature of being able to name an interface block the same as the type name gives me options to apply generics on constructors that are sufficient and flexible enough for my needs.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I also tend to use constructors, but in this very particular case, the default constructors suit me perfectly. There are no additional components that I need to initialize by hand, etc. But sure, the initializer (using the interface to use the same name as the type as you said) is the one I had to implement so far...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What you propose looks like a duplicate component name declaration. I understand what you want to accomplish, but that's just not how the language tends to work. As you found, it is easy to write your own constructors.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Steve,
But why would it be a problem? As long as the type of the component is identical to the parent one, redefining the default initialization should not break anything.
Along these lines, I have another question. What is the correct way to set inherited private components? Let's suppose I have the following types:
module foo type, abstract :: Dad private integer :: i end type type, extends(Dad) :: Son end type end module program main use foo type(Son) :: guy guy=Son(i=3) ! i is private guy%dad=Dad(i=3) ! Dad cannot be "instantiated", it's abstract end program
...
What is the correct way to set the component i of something variable? Are getters/accessors the only possibilities?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Extended derived types (i.e., children class) have access to parent members, so you can add a "setter" method to your child class: say you create SUBROUTINE called SetI which takes an argument ValueOfI. Your program can then invoke this as CALL Son%SetI(ValueOfI=3).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, this is not 100% true. Dad's private component is accessible if Son is defined in the same module. The following code does not compile:
module foo implicit none public :: Dad private type, abstract :: Dad private integer :: i end type end module module foo2 use foo implicit none public :: Son private type, extends(Dad) :: Son contains procedure :: set_i end type interface Son module procedure :: Son_init end interface contains subroutine set_i(self,i) class(Son), intent(inout) :: self integer :: i self%i=i end subroutine function Son_init(i) result(new) integer, intent(in) :: i type(Son) :: new new%i=i end function end module program main use foo2 implicit none type(Son) :: guy guy=Son(i=3) end program
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yep, that's one of the limitations of the current Fortran standard, including 2008. So you have to either apply PUBLIC attribute to component i in the ABSTRACT type or include both the parent and child in the same module.
I end up picking one of these options depending on my needs. I usually create a concrete base type off the abstract in the parent module with "getter" and "setter" methods; child modules then extend the concrete type instead of the abstract.
In one case, I ended up with several concrete types (analogy: abstract shape class; concrete bases for 2-D and 3-D; children: triangle, circle, etc. for 2-D and sphere, cylinder, pyramid, etc. for 3-D), abstract and concretes all in one (parent) module, but the children were in their own individual modules.
And yes, this won't satisfy OOP-purists but one is constrained by the language features.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think the constructor method is definitely the way to go here; a little bit more typing, but the client code can remain unchanged, so you don't have to repeat yourself:
module foo implicit none private public :: bar ,rab type :: bar private integer :: a=53 end type type, extends(bar) :: rab end type interface rab procedure :: constructor end interface contains function constructor(a) result(res) integer ,optional ,intent(in) :: a type(rab) :: res res%a = -33333 if ( present(a) ) res%a = a end function end module
If you want to allow the child and the parent to be contained in separate modules, you could create a type bound setter method for the abstract type (you could even make the input argument optional, and use a default if the input argument is omitted) then call the setter method from the constructor. One downside here, however, is that the setter method will now be publically exposed.
module foo implicit none private public :: bar type :: bar private integer :: a=53 contains procedure :: a_setter end type contains subroutine a_setter(this,a) class(bar) ,intent(out) :: this integer ,optional ,intent(in) :: a res%a = 53 if ( present(a) ) this%a = a end subroutine end module module oof use foo implicit none private public :: rab type, extends(bar) :: rab end type interface rab procedure :: constructor end interface contains function constructor(a) result(res) integer ,optional ,intent(in) :: a type(rab) :: res call res%a_setter(-33333) if ( present(a) ) call res%a_setter(a) end function end module
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yep, Zaak, this is pretty much exactly the only solution I had figured so far.
Thanks!

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