I have a base library with is used by two different applications. We changed some stuff in the base library recently and are now adapting the applications to this change. Today I stumbled over some code that smells like a good idea to do it in an object oriented way, but the more I think about it, the less I think Fortrans OO-features are capable of this.
But in detail: We have a routine that operates on a type and uses one if it's properties. Lets call it container:
type element
integer :: id
end type element
type container
type(element), allocatable :: elements(:)
end type container
Each application is now able to extend this type:
type, extends(container) :: myContainer
!...
end type myContainer
Until here everything is pretty fine. But one if the application needs to extend the element type as well:
type, extends(elemet) :: myElement
integer :: someOtherStuff
end type myEement
When I got everthing right, it is possible to add instances of myElement to myContainer%elemets, at least using myElement%element. But is it also possible to get the original instance out of myContainer%element?
Consider the following code:
type(myElement) :: element, after
type(myContainer) :: container
allocate(myContainer%elements(1))
!will result in Can't convert TYPE(myElement) to TYPE(element)
!myContainer%elements(1) = element
myContainer%elements(1) = element%element
! vice versa from above
!after = myContainer%elements(1)
after%element = myContainer%elements(1)
I could assign the element from the list to after%element, but all data specific to myElement wouldn't be set. I guess the data is already lost when assigning element%element to the list? So is there any way to achieve some kind of type preservation in Fortran which would also preserve the information of myElement even when adressing it's instance as element?
In other languages, e.g. C# you can assign a subclass to a collection of superclasses, get the instance back and use it as a subclass again, because the complete object was stored in the collection and it was just addressed as an instance of the superclass. When addressed as a subclass again, it still contains all information it had before it was added to the collection.
Is there something similar in Fortran?
You can make the container be able to contain a polymorphic value
type container
class(element), allocatable :: elements(:)
end type container
then you can allocate the array elements to a type which is extended from element.
When you just assign element%element you only copy a part of the extended type which corresponds to the base type.
Related
I am new to Kotlin,
data class RewardDetail(
val name: String
val isActivated: Boolean
val amountInCents: Int?
val Campain: String?
val expirationDate: Long?
)
class Rewards(Array<Reward>)
class Reward(
val name: String
isActive: Boolean
amountInCents: Int
campaignId: String
expirationDate: LocalDateTime
)
val details : List<RewardDetail> = blablabla
val rewards = Rewards(details)
can details cast to rewards successfully?
Also note campaignId and Campain field name are different in RewardDetail and Reward and some fields can be nullable in RewardsDetail
What is the best way to handle situation like this?
Kotlin is strongly-typed. You can never successfully cast one thing into a different class. You can only cast an object into a type that it already satisfies. For example, if you have an Int that is currently only known to the compiler to be a Number, you can cast to Int to tell the compiler that it has an Int, so the compiler will allow you to use the functions that are specific to Int. But nothing but an Int can ever be cast to an Int.
So, unlike weakly typed languages, casting does not convert from one type to another. Casting is only you making a promise to the compiler that an object already is of the other type.
In your example, the only way to get a RewardDetail from a Reward is by writing a function that manually converts each property to the appropriate type.
The Rewards class above is largely redundant. There's no need for a wrapper class around a single Array or List unless you need to do validation of items added to or retrieved from the list. In that case, it would probably make more sense to create a subclass of ArrayList for that purpose, so you could still easily iterate the list and use all the List and Iterable helper functions on it.
Probably about 95% of the time, you should prefer using List over using Array. Arrays should be used only when you need a fixed size collection that is also mutable, or if you are working with highly performance-critical code. The reason it should be limited to these uses is that mutability should be avoided when possible for robustness and Arrays are more cumbersome to work with than MutableLists.
A typical implementation of a function that converts from one type to another would be to write an extension function RewardDetail.toReward() extension function, or a toReward() function inside the RewardDetail class. However, in your case you need to decide what you need to happen when some of the values of RewardDetail are null. Maybe you just return null so your conversion function should be toRewardOrNull(), or you provide default values for the properties that have no value in RewardDetail.
I'm trying to write a subroutine in a MEX file to convert Fortran derived types to MATLAB structs. I'd like to automate the process because I have a derived type with multiple components that are themselves derived types, so manually converting every component would take a very long time.
I found one other question related to this that suggests it's not possible to access these components as strings: Is there a way to call the field of a derived type using a string?
Barring that, I was thinking there might be a way to get the number of components and access each one by a numeric index, but I haven't found anything indicating that this is possible. None of the derived types I'm dealing with have procedure components, just variables.
Can I access these variables in a generic way, like myObj%(1)?
The answer is the same as in the linked question. No, no such indexing is possible.
EDIT to provide more details:
1) The code that provides the libraries cannot be (easily) changed so profile_v1_type and profile_v2_type should be assumed to be immutable.
I have implemented #francescalus suggestion and it works for my small test case, but I was insufficiently clear about the problem, I think. The reason being that I can only modify my code not the code/types coming from the library. The problem will be that both will have t in the profile_type that gets imported which clash with the parent type.
But I am going to implement something where I replicate the contents of the derived type that I want and then use pointers and type-bound procedures to point to the components of the profile_type version that I want to use. It's not as clean as I wanted it to be but it's much better than I have now.
I am supporting a code that interfaces with another that has 2 versions - the two versions are very similar in interface and although the inputs and outputs are identical in property, they are obviously different derived types (they come from different libraries and differ slightly in the variables contained within. Most variable names inside these types are the same though crucially).
It is (apparently) necessary to support both at runtime, otherwise I would preprocess this all at compile time.
At the moment I have lazily copied and pasted the same code for each version (and all of the versions of derived types it uses) into separate subroutines (*_v1.f90, *_v2.f90).
This is annoying and not very maintainable.
What I'd like to be able to do is use some kind of pointer that doesn't care about what it's pointing to (or rather gets its type information from what it points to and is smart enough to know what's inside).
As I said above, the names are mostly the same, e.g. (t, for temperature, say)
From v1 of library:
TYPE profile_v1_type
REAL :: t
! loads of other stuff
END TYPE profile_v1_type
From v2 of library:
TYPE profile_v2_type
REAL :: t
! loads of other stuff, more than the first version
END TYPE profile_v2_type
In my code:
TYPE profile_container_type
TYPE(profile_v1_type) :: profile_v1
TYPE(profile_v2_type) :: profile_v2
! other arrays that are common inputs to both
END TYPE
! It's actually USE'd then allocated and initialised elsewhere, but I hope you get the idea
!USE profile_container_mod, ONLY : profile_container
TYPE(profile_container_type), TARGET :: profile_container
TYPE(*) :: p
REAL :: t1
!Version determined by a namelist
IF (Version == 1) THEN
p => profile_container % profile_v1
ELSE IF (Version == 2) THEN
p => profile_container % profile_v2
ENDIF
t1 = p % t + 1
.
.
.
ifort 19 gives these (expected) errors:
test.f90(24): error #8776: An assumed type object must be a DUMMY argument. [P]
TYPE(*), POINTER :: p
--------------------^
test.f90(24): error #8772: An assumed type object must not have the ALLOCATABLE, CODIMENSION, POINTER, INTENT(OUT) or VALUE attribute. [P]
TYPE(*), POINTER :: p
--------------------^
test.f90(39): error #6460: This is not a field name that is defined in the encompassing structure. [T]
t1 = p % t + 1
---------^
compilation aborted for test.f90 (code 1)
replace TYPE(*) with CLASS(*) gives the (still expected):
test2.f90(39): error #6460: This is not a field name that is defined in the encompassing structure. [T]
t1 = p % t + 1 ! or some clever function...
---------^
compilation aborted for test2.f90 (code 1)
This is fixed by SELECTing the type that you want to handle, but my point is that I want to do the same thing for either the v1 and v2 code (it will never be both). And I want to do it many times, not in this routine but in about a dozen routines.
I am open to using C pointers if the responder is able to provide a simple example to follow. I have tried (not recently) to solve this problem using C interoperability, but obviously without success!
Unlimited polymorphic entities are not the correct approach here.
Instead, we can define a base type which incorporates all of the common data and processing for the various other types. Here, let's call this base type profile_base_type:
type profile_base_type
real t
end type
The other two specific profiles can extend this base:
type, extends(profile_base_type) :: profile_v1_type
! v1 specific parts
end type
type, extends(profile_base_type) :: profile_v2_type
! v2 specific parts
end type
Then we can declare a polymorphic pointer of the base type
class(profile_base_type), pointer :: p
which can point to targets of either of the extending types:
p => profile_container%profile_v1
p => profile_container%profile_v2
Now, we can access the components of p which are in the type profile_base_type
t1 = p%t + 1
without having to use a select type construct.
Naturally, those specific aspects of the extending types cannot be accessed in this way but there are other considerations for that.
Updating some archaic F77 that no longer fully supported our needs. I am looking for the functional equivalent of VB's "WITH" statement to support the conversion from a mass of F77 disconnected, individual variables to hierarchical derived Types. While the code is much easier to read and understand the downside is that the code becomes very cumbersome and prone to typos. So, the use of WITH would greatly ease the conversion burden.
VB's "WITH" statement executes a series of statements on a single object or a user-defined type.
Example:
if I want to reference elements my derived Type named Loads I would write code with Loads% prefixing each element and that is cumbersome. The WITH statement allows one to re-write the block with an assumed reference to Loads%.
WITH Loads%
ID = blah
Description = blahblah
Duty(I) = 2
End WITH
Suggestions...?
There's no Fortran construct which provides a precise analog to what you describe as VB's with statement. For your particular example, you could write something along the lines of ...
Given a derived type definition such as
type :: load
character(4) :: id
character(32) :: description
integer, dimension(4) :: duties
end type load
and a variable of that type
type(load) :: loads
you can use a default constructor to set the values of the members of loads, like this:
loads = load('myid', 'my description', [1,2,3,4])
or even like this:
loads = load(duties=[3,4,5,6], id = 'id2', description='description')
If you look around on SO for Qs and As on the subject of Fortran derived type constructor you'll find out how to build more complicated constructors which don't need all the members to be given values when they are called. There are some useful resources elsewhere on the internet too.
If one of your concerns is to avoid typing long, and possibly multipart, entity names then the associate construct might help. For example, if, rather than loads the name of the variable you wanted to avoid typing was something like long%structured%entity you might write
associate (shnm => long%structured%entity`)
shnm%id = 'idxx'
*etc*
end associate
I'm sure you could easily come up with more extensive examples of the use of with which would not be easy to translate to Fortran without repeated writing of loads%.
Lets say I have a List<object> which is passed into a class as an argument, this list should contain a bunch of models for my application all of the same type. Is it then possible for me to somehow retrieve the type of the list which was passed in? (without calling GetType() on a item in the list).
For example, I pass in List<User> which is stored as List<object>, can I now retrieve the type User from the list without doing something like:
List<object> aList;
aList[0].GetType();
Well, you can use:
Type elementType = aList.GetType().GetGenericArguments[0];
However, that will fail if you pass in FooList which derives from List<Foo> for example. You could walk the type hierarchy and work things out appropriately that way, but it would be a pain.
If at all possible, it would be better to use generics throughout your code instead, potentially making existing methods generic - e.g. instead of:
public void Foo(List<object> list)
you'd have
public void Foo<T>(List<T> list)
or even
public void Foo<T>(IList<T> list)
If you just need it for the very specific case where the execution-time type will always be exactly List<T> for some list, then using GetGenericArguments will work... but it's not terribly nice.
As I understand it, the purpose of generics is to not have to do the type checking manually. The compiler ensures that the items in the list are the type they claim to be, and therefore the items that come out will be that type.
If you have a List<object>, you're defeating the purpose of using generics at all. A List<object> is a list that can store any type of object, no matter what types you actually put into it. Therefore, the onus is upon you to detect what the actual type of the object you retrieve is.
In short: you have to use GetType.