Hello,
I have been trying to make a small program to develop my understanding of the SOLID principles, as well as get a better understanding of OOP in modern Fortran.
To do this I have made an abstract class that represents a number, and will then implement various categories of number. So far I am struggling with correctly specifying the correct abstract interface for addition.
This is the best I have come up:
module number_mod
implicit none
type, abstract :: NumberClass
private
contains
procedure(addNumberInterface), deferred :: add
end type
abstract interface
function addNumberInterface(self, other) result(answer)
import NumberClass, RealClass
class(NumberClass), intent(in) :: self
class(*), intent(in) :: other
class(RealClass), allocatable :: answer
end function addNumberInterface
end interface
type, extends(NumberClass) :: RealClass
real :: real_part
contains
procedure :: add => addReal
generic, public :: operator(+) => add
end type
contains
function addReal(self, other) result(answer)
class(RealClass), intent(in) :: self
class(*), intent(in) :: other
class(RealClass), allocatable :: answer
select type(other)
type is(RealClass)
allocate(RealClass :: answer)
select type(answer)
type is(RealClass)
answer = RealClass(self%real_part + other%real_part)
end select
type is (real)
allocate(RealClass :: answer)
select type(answer)
type is(RealClass)
answer = RealClass(self%real_part + other)
end select
class default
print *, "UHOH"
end select
end function addReal
It allows for other
to have multiple types, but it also allows addReal
to be called with other
being any type. For example:
class(RealClass) :: a, b, c
a = RealClass(3)
b = RealClass(4)
c = a + b ! I want this case to be valid and the compiler is happy with it
c = a + 3 ! I do not want this case to be valid but the compiler is happy with it due to class(*)
c = a + "hello" ! I do not want this case to be valid either
In addition addNumberInterface
is still not correct as if I were to create type, extends(NumberClass) :: ComplexClass
then addNumberInterface
would mean the procedure that overloads add
would return type RealClass
whereas I would like it to return ComplexClass
.
Can any one help?