I don’t to write getter and setter subrountine
Could you elaborate a bit? Why do you want protected? Can private not do the job?
Your question, or rather statement, does not provide much information about the problem you trying to solve and that causes us to guess. Which may or may not turn out to be useful.
Just like @Arjen said, please elaborate.
But keep in mind that, unlike other programming languages, in Fortran the public
|protected
|private
attributes belong to the module, not to the derived type.
Not entirey:
module privatetype
implicit none
type :: mytype
private
integer :: x
end type mytype
end module
program test_privatetype
use privatetype
type(mytype) :: y
y%x = 1
end program test_privatetype
This fails because of the direct access to component x.
When it comes to avoiding a “getter” procedure, I suspect what @weixing1531 would like to do is to provide direct read-only access to a component
type :: mytype
private
integer, protected :: x
end type
There was a proposal several years ago to do exactly that, but as I recall there was sharp disagreement in the committee about (I think) how that would behave when extending the type, and the whole thing got scuttled.
There might be issues with the structure constructor of an (outside the base module) extended type —e.g., when the base type is abstract and/or the protected component has no default initialization.
But the accessor pattern (imo) is just a Java thing and if you only need the getter but not the setter, or vice versa, then the component should just be either public or a constant/parameter.
(The Go style guide actually suggests using it only when absolutely necessary, and even then, avoiding the “Get” prefix in the getter.)
This page seems to have a lot of related info. I also think this feature would be useful if some components are not to be modified via direct component access.
To “emulate” this feature, I typically attach an underscore at the end of component names (e.g., “integer :: foo_”) so that I can recall that I should not modify this component directly (but rather I should use a proper setter routine). In my case, derived types are given a type-bound procedure set()
, which handles the assignment of all such variables via keyword arguments (in order to perform any additional things associated with each assignment).
I had completely forgotten about that thread; thanks for linking it!
Just out of interest, does the above caveat about “accessor pattern” also refer to my use case (where I want to “read” a field/component directly with no potential overhead, while requiring the use of a setter to guarantee any additional stuff to be done for assignment)? I remember it is not generally recommended to write “setters/getters” to all fields of a class as an attempt of encapsulation (like in old Java or OO books), but the above “asymmetric” need for direct read of a field + setter routine seems more common and reasonable to me (for performance + maintainance reasons etc).
In my case, even when the performance is not a problem, I do not want to write getter/setter routines in many cases either, simply because it is tedious to write module procedures for that purpose (as compared to other languages where one-liners are often possible).
There’s nothing wrong with the accessor pattern. But it’s often overused unnecessarily.
If the component cannot easily accommodate to value changes (e.g., if it’s an int enum, must be unsigned, must lie within a given range, etc.), then having a setter is fine. Although, just doing a sanity check when that value is actually used in the code, and returning an error, is even better (imho).
(I suppose Fortran 2023 enumerator types
, and the not-yet-standardized unsigned
can help a little bit.)
Your single-setter with optional args is actually a nice touch, since it avoids the overhead common in languages where chaining is allowed.
Thanks for your comments! I also read web articles about this trend (for old OO codes and Java), and I was wondering about the recommendation of the Go community(?) about accessors in general, because it may depend on the culture (? or history) of the language.
In my case they are simulation parameters and some data, and they are associated with other params/data, so any change should be done consistently (with additional changes of other data and checks if necessary). I feel derived types + setters are convenient for this kind of self management.
Getters are most of time unnecessary. Setters are sometimes justified. And that’s where a protected
attribute would have been useful.