Fortran
객체 지향 프로그래밍
수색…
파생 된 형식 정의
Fortran 2003은 객체 지향 프로그래밍을 지원합니다. 이 기능을 사용하면 최신 프로그래밍 기술을 활용할 수 있습니다. 파생 된 유형은 다음 형식으로 정의됩니다.
TYPE [[, attr-list] :: ] name [(name-list)]
[def-stmts]
[PRIVATE statement or SEQUENCE statement]. . .
[component-definition]. . .
[procedure-part]
END TYPE [name]
어디에,
- attr-list - 속성 지정자의리스트
- name - 파생 데이터 형의 이름
- name-list - 쉼표로 구분 된 유형 매개 변수 이름 목록
- def-stmts - name-list에 명명 된 유형 매개 변수 중 하나 이상의 INTEGER 선언
- component-definition - 파생 형식의 구성 요소를 정의하는 하나 이상의 형식 선언 문 또는 프로 시저 포인터 문
- procedure-part - CONTAINS 문 다음에 PRIVATE 문과 하나 이상의 프로 시저 바인딩 문
예:
type shape
integer :: color
end type shape
유형 절차
클래스와 비슷한 행동을 취하기 위해서는 타입과 관련 프로 시저 (서브 루틴과 함수)가 하나의 모듈에 배치되어야한다 :
예:
module MShape
implicit none
private
type, public :: Shape
private
integer :: radius
contains
procedure :: set => shape_set_radius
procedure :: print => shape_print
end type Shape
contains
subroutine shape_set_radius(this, value)
class(Shape), intent(in out) :: self
integer, intent(in) :: value
self%radius = value
end subroutine shape_set_radius
subroutine shape_print(this)
class(Shape), intent(in) :: self
print *, 'Shape: r = ', self%radius
end subroutine shape_print
end module MShape
나중에 코드에서이 Shape 클래스를 다음과 같이 사용할 수 있습니다.
! declare a variable of type Shape
type(Shape) :: shape
! call the type-bound subroutine
call shape%set(10)
call shape%print
추상 파생 된 유형
확장 가능한 파생 형식은 추상적 일 수 있습니다.
type, abstract :: base_type
end type
이러한 파생 된 유형은 다음과 같이 인스턴스화 할 수 없습니다.
type(base_type) t1
allocate(type(base_type) :: t2)
그러나 다형성 객체는 이것을 선언 된 타입으로 가질 수있다.
class(base_type), allocatable :: t1
또는
function f(t1)
class(base_type) t1
end function
추상 타입은 컴포넌트와 타입 - 바운드 프로 시저를 가질 수있다.
type, abstract :: base_type
integer i
contains
procedure func
procedure(func_iface), deferred :: def_func
end type
프로 시저 def_func
는 인터페이스 func_iface
가있는 지연된 유형 바인딩 프로 시저입니다. 이러한 지연된 타입 - 바운드 프로시 저는 각각의 확장 타입에 의해 구현되어야한다.
유형 확장
파생 된 유형은 bind
속성이나 sequence
속성이없는 경우 확장 가능 합니다. 이러한 유형은 다른 유형으로 확장 될 수 있습니다.
module mod
type base_type
integer i
end type base_type
type, extends(base_type) :: higher_type
integer j
end type higher_type
end module mod
선언 형와 다형 변수 base_type
유형과 호환 타입 higher_type
그 동적 타입을 가질 수있다
class(base_type), allocatable :: obj
allocate(obj, source=higher_type(1,2))
유형 호환성은 하위 체인을 통해 내려 지나지 만 유형은 한 유형 만 확장 할 수 있습니다.
확장 파생 형은 부모로부터 형식 바인딩 된 프로 시저를 상속 받지만이를 재정의 할 수 있습니다.
module mod
type base_type
contains
procedure :: sub => sub_base
end type base_type
type, extends(base_type) :: higher_type
contains
procedure :: sub => sub_higher
end type higher_type
contains
subroutine sub_base(this)
class(base_type) this
end subroutine sub_base
subroutine sub_higher(this)
class(higher_type) this
end subroutine sub_higher
end module mod
program prog
use mod
class(base_type), allocatable :: obj
obj = base_type()
call obj%sub
obj = higher_type()
call obj%sub
end program
유형 생성자
인터페이스를 사용하여 형식 이름을 오버로드하여 파생 형식에 대해 사용자 지정 생성자를 만들 수 있습니다. 이 방법으로, 해당 유형의 오브젝트를 구성 할 때 구성 요소와 일치하지 않는 키워드 인수를 사용할 수 있습니다.
module ball_mod
implicit none
! only export the derived type, and not any of the
! constructors themselves
private
public :: ball
type :: ball_t
real :: mass
end type ball_t
! Writing an interface overloading 'ball_t' allows us to
! overload the type constructor
interface ball_t
procedure :: new_ball
end interface ball_t
contains
type(ball_t) function new_ball(heavy)
logical, intent(in) :: heavy
if (heavy) then
new_ball%mass = 100
else
new_ball%mass = 1
end if
end function new_ball
end module ball_mod
program test
use ball_mod
implicit none
type(ball_t) :: football
type(ball_t) :: boulder
! sets football%mass to 4.5
football = ball_t(4.5)
! calls 'ball_mod::new_ball'
boulder = ball_t(heavy=.true.)
end program test
이것은 별도의 초기화 루틴을 사용하는 것보다 깔끔한 API를 만드는 데 사용할 수 있습니다.
subroutine make_heavy_ball(ball)
type(ball_t), intent(inout) :: ball
ball%mass = 100
end subroutine make_heavy_ball
...
call make_heavy_ball(boulder)