Предположим, у меня есть абстрактный базовый класс Shape_t
с производными типами Rectangle_t
и Circle_t
. Существует обобщенная c функция get_area
для обоих производных типов, и я хотел бы также перегрузить ее для класса, чтобы я получил следующие интерфейсы (нотация Джулиана):
get_area(type(Circle_t) :: C)
get_area(type(Rectangle_t) :: R)
! The following leads to ambiguous interfaces
get_area(class(Shape_t) :: S)
К сожалению, я получить ошибку "неоднозначный интерфейс", когда я пытаюсь это сделать. Отсюда у меня три вопроса:
Есть ли что-то концептуально неправильное в том, чего я хочу достичь? Поскольку переменные явно объявлены как polymorphi c (class(...)
), компилятор всегда может выбрать наиболее конкретный c интерфейс и вернуться к интерфейсу polymorphi c. Поэтому я не вижу двусмысленности.
Если ответ на вопрос 1: «Не существует концептуальной двусмысленности». Есть ли в стандарте планы изменить это?
Приведен ли следующий код, в котором введен dyn_get_area
для динамического c полиморфизма, solid обходной путь? Обратите внимание, что я хотел бы придерживаться полиморфизма stati c как можно дольше, то есть до тех пор, пока конкретная форма известна во время компиляции.
module shapes_mod
implicit none
private
public :: Shape_t, Rectangle_t, Circle_t, PI, get_area, dyn_get_area
real, parameter :: PI = atan(1.0) * 4.0
type, abstract :: Shape_t
end type
type, extends(Shape_t) :: Circle_t
real :: r = 0.0
end type
type, extends(Shape_t) :: Rectangle_t
real :: a = 0.0, b = 0.0
end type
interface get_area
module procedure get_area_Rectangle_t, get_area_Circle_t
end interface
contains
pure function get_area_Circle_t(C) result(res)
type(Circle_t), intent(in) :: C
real :: res
res = C%r**2 * PI
end function
pure function get_area_Rectangle_t(R) result(res)
type(Rectangle_t), intent(in) :: R
real :: res
res = R%a * R%b
end function
pure function dyn_get_area(S) result(res)
class(Shape_t), intent(in) :: S
real :: res
select type(S)
type is(Rectangle_t)
res = get_area(S)
type is(Circle_t)
res = get_area(S)
end select
end function
end module
program test_polymorphic_and_static_overload
use shapes_mod, only: Shape_t, Rectangle_t, Circle_t, get_area, dyn_get_area
implicit none
class(Shape_t), allocatable :: random_shape
type(Circle_t) :: circle
type(Rectangle_t) :: rectangle
real :: p
circle = Circle_t(1.0)
rectangle = Rectangle_t(1.0, 2.0)
call random_number(p)
if (p < 0.5) then
random_shape = circle
else
random_shape = rectangle
end if
write(*, *) get_area(circle)
write(*, *) get_area(rectangle)
write(*, *) dyn_get_area(random_shape)
end program