データはmodule内にまとめることができます。一般的な形式は以下の通りです。
module 
    [use ]
    []
contains
    []
end module []
3つのアクセスプロパティがあります: public, private, protected。
public: 外部のコードから読み書きが可能です。
private: 外部のコードからアクセスできません。
public, protected: 外部のコードから読み取りが可能です。
モジュールの公開データを外部のコードに含めることができます。 3つの方法があります。
module test_m
    implicit none
    private  ! すべてのデータはデフォルトで非公開です。
    ! これらの手続きはpublicに設定され、モジュールの外部からアクセス可能です。
    public print_coords, set_coords 
    real :: x, y  ! モジュールの外部からはアクセスできません。
contains
    subroutine print_coords
        print *, "x, y", x, y
    end subroutine
    subroutine set_coords(new_x, new_y)
        real, intent(in) :: new_x, new_y
        x = new_x
        y = new_y
    end subroutine
end module
program main
    use test_m   ! "test_m"モジュールをインポートします
    implicit none
    call set_coords(1.0, 1.0)  ! test_modからpublicな手続きを呼び出します。
    call print_coords
end program
module data_access_m
    implicit none
    private
    public a, b
    protected b
    private c
    integer :: a = 1
    integer :: b = 1
    integer :: c = 1
end module
program main
    use data_access_m
    ! publicオブジェクトへのアクセスは可能です。
    print *, a
    ! publicオブジェクトの編集は可能です。
    a = 2
    ! protectedオブジェクトへのアクセスは可能です。
    print *, b
    ! protectedオブジェクトの編集はできません。
    !b = 2 <- エラー
    ! privateオブジェクトへのアクセスはできません
    !print *, c <- エラー
    ! privateオブジェクトの編集はできません
    !c = 2 <- エラー
end program
module test_module
    implicit none
    private
    integer, public :: a = 1
    integer, public, protected :: b = 1
    integer, private :: c = 1
end module test_module
!> test_moduleのすべての公開データをインポートします。
program main
    use test_module
    print *, a, b
end program main
!> すべてのデータをインポートし、名前を変更します。
program main
    use test_module, better_name => a
    ! 新しい名前が利用可能です。
    print *, better_name
    ! 古い名前はもう利用できません。
    !print *, a  <- エラー
end program main
!> 公開データのサブセットのみをインポートします。
program main
    use test_module, only : a
    ! aだけがロードされます。
    print *, a
    ! bはロードされません。
    !print *, b  <- エラー
end program main
モジュールはサブモジュールを使用して拡張することができます。複数の利点があります
2つのモジュールがお互いからデータを必要とする場合。
!> 円に関する簡単なモジュール
module circle_mod
    implicit none
    private
    public :: area, radius
    real            :: radius
    real, parameter :: PI = 3.1415
    interface  ! インターフェースブロックが必要です。サブモジュール経由で実装される各機能には、ここにエントリが必要です。
        module function area() ! 重要です。"module"キーワードに注意してください。
            real :: area
        end function 
    end interface
end module 
submodule (circle_mod) circle_subm   ! サブモジュール (親モジュール) 子モジュール.
contains
    module function area()  ! 再び "module" キーワード。
        area = PI*radius**2
    end function 
end submodule
program main
    use circle_mod
    implicit none
    radius = 1.0
    print *, "area:", area()
end program 
Fortranでは、他の構造から構造を派生させることができます。これを「派生データ型」と呼び、派生型は親型の特徴を持ち、新たに追加されたものも持ちます。一般的な構文は以下の通りです。
type, extends() :: 
end type
次の例は、会社内の異なるタイプの人々を示しています。
module company_data_mod
    implicit none
    private
    public phone_type, address_type, person_type, employee_type, salaried_worker_type, hourly_worker_type
    type phone_type
        integer :: area_code, number
    end type
    type address_type
        integer                        :: number
        character (len=:), allocatable :: street, city
        character (len=2)              :: state
        integer                        :: zip_code
    end type
    type person_type
        character (len=:), allocatable :: name
        type (address_type)            :: address
        type (phone_type)              :: phone
        character (len=:), allocatable :: remarks
    end type
    type, extends (person_type) :: employee_type
        integer :: phone_extension, mail_stop, id_number
    end type
    type, extends (employee_type) :: salaried_worker_type
        real :: weekly_salary
    end type
    type, extends (employee_type) :: hourly_worker_type
        real :: hourly_wage, overtime_factor, hours_worked
    end type
end module
program main
    use company_data_mod
    implicit none
    type (hourly_worker_type) :: obj
end program
オブジェクトが自動的に削除される前に呼び出される手続きを定義することができます。これはfinalステートメントで行われます。次の例を参照してください。
module person_m
    implicit none
    type person
        integer, allocatable :: numbers(:)
    contains
        final :: del
    end type
contains
    subroutine del(this)
        !! 派生型のデストラクタの例。 allocatables は 
        !! 自動的に解放されるので、これは final の使用法を示すだけです。
        type (person), intent (inout) :: this
        if (allocated(this%numbers)) deallocate (this%numbers)
    end subroutine 
end module 
基底型をabstractとして設定することで、その型のオブジェクトを初期化できなくなりますが、その型のサブタイプを派生させることはできます（extendsを使用）。サブタイプで定義する必要のある特定の手続きは、deferredプロパティを持つ必要があり、明示的なインターフェースが必要です。
以下の例はその使用方法を示しています。
module shape_m
    implicit none
    type, abstract :: shape
        real :: a, b
    contains
        procedure :: print => shape_print
        procedure (area_shape), deferred :: area
    end type
    interface
        real function area_shape(this)
            import :: shape
            class (shape), intent (in) :: this
        end function
    end interface
contains
    subroutine shape_print(this)
        class (shape), intent (in) :: this
        print *, 'a,b', this%a, this%b
    end subroutine
end module
module line_m
    use shape_m
    implicit none
    private
    public line
    type, extends (shape) :: line
    contains
        procedure :: area
    end type
contains
    real function area(this)
        class (line), intent (in) :: this
        area = abs(this%a - this%b)
    end function
end module
module rectangle_m
    use shape_m
    implicit none
    private
    public rectangle
    type, extends(shape) :: rectangle
    contains
        procedure :: area
    end type
contains
    real function area(this)
        class (rectangle), intent (in) :: this
        area = this%a * this%b
    end function
end module
program main
    use line_m
    use rectangle_m
    implicit none
    type (line)      :: l
    type (rectangle) :: r
    ! line
    l%a = 2.0
    l%b = 4.0
    print *, "line ...  "
    call l%print
    print *, "-> from:  ", l%a
    print *, "-> to:    ", l%b
    print *, "-> length:", l%area()
    ! rectangle
    r%a = 3.0
    r%b = 5.0
    print *
    print *, "rectangle ..."
    call r%print
    print *, "-> side a:", r%a
    print *, "-> side b:", r%b
    print *, "-> area:  ", r%area()
end program
allocate文での型定義とselect type環境を使用して、子クラスへのポインタを作成することができます。
以下の例ではその使用方法を強調しています。
module shape_m
    implicit none
    type, abstract :: shape
        ! 親クラスを実装するために使用される空のクラスです。
        ! abstract の理由: TYPE(!) shapeのオブジェクトは存在しないはずです。
        ! ポリモーフィックCLASSのインスタンスのみ。
    end type
end module
module line_m
    use shape_m
    implicit none
    type, extends (shape) :: line
        ! 1つの属性を持つ子クラスです。
        ! extends(shape)の理由: ポリモーフィックshapeポインタは
        ! この型のオブジェクトを指すことができます。
        real :: length
    end type
end module
module rectangle_m
    use shape_m
    implicit none
    type, extends (shape) :: rectangle
        ! 別の属性を持つ子クラスです
        ! extends(shape)の理由: (lineの説明を参照)
        real :: area
    end type
end module
program main
    use rectangle_m
    use line_m
    implicit none
    class (shape), allocatable :: sh  ! 親クラスへのポインタ。
    ! allocate (line :: sh)
    allocate (rectangle :: sh)  ! 子型を使用して割り当てます
    select type (x => sh)   ! アソシエーションブロック。"x"は子オブジェクトへのポインタおよびその型になります(!!)
        type is (line)      ! 正しい子タイプを選択します (allocateステートメントで使用したもの)
            x%length = 1.0
            print *, 'line length', x%length
        type is (rectangle)
            x%area = 2.0
            print *, 'rectangle area', x%area
        ! class is ()  ! クラスを使用して選択します。
        class default  ! 何も適用されなかった場合。
            error stop 'class/type not specified!'
    end select
end program
ここでは、Fortranに関連するオブジェクト指向プログラミングの用語をまとめます。
データや手続きをまとめた単位。
カプセル化や再利用性を促進する。
moduleブロックで宣言し、end moduleで終了する。
public, private, protectedの3つのアクセスプロパティがある。
public: 外部コードから読み書き可能。
private: 外部コードからアクセス不可。
protected: 外部コードから読み取り可能。
外部のコードでモジュールのデータや手続きを使用する方法。
use でモジュールをインポートする。
use , only: で一部のデータや手続きのみをインポートする。
大規模なモジュールをさらに分割するための仕組み。
インターフェースと実装を分離し、依存関係を管理する。
他のデータ型から派生した新しいデータ型。
type, extends() :: の形式で宣言する。
オブジェクトが削除される前に実行される手続き。
リソースの解放や後処理を行うために使用される。
インスタンスを作成できない抽象的な型。
派生型は抽象基底型から派生して具体的な型を作成する。
派生型で実装する必要のある手続き。
抽象基底型で定義され、具体的な型で実装される。
異なる型のオブジェクトに対して同じポインタを使用できる仕組み。
実行時に異なる型のオブジェクトを操作するために使用される。
これらの用語を理解することで、Fortranでオブジェクト指向プログラミングをより効果的に行うことができます。