<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://climate-cms.wikis.unsw.edu.au/index.php?action=history&amp;feed=atom&amp;title=Object-oriented_Fortran</id>
	<title>Object-oriented Fortran - Revision history</title>
	<link rel="self" type="application/atom+xml" href="http://climate-cms.wikis.unsw.edu.au/index.php?action=history&amp;feed=atom&amp;title=Object-oriented_Fortran"/>
	<link rel="alternate" type="text/html" href="http://climate-cms.wikis.unsw.edu.au/index.php?title=Object-oriented_Fortran&amp;action=history"/>
	<updated>2026-10-04T16:53:14Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.31.0</generator>
	<entry>
		<id>http://climate-cms.wikis.unsw.edu.au/index.php?title=Object-oriented_Fortran&amp;diff=733&amp;oldid=prev</id>
		<title>S.wales at 05:29, 18 March 2019</title>
		<link rel="alternate" type="text/html" href="http://climate-cms.wikis.unsw.edu.au/index.php?title=Object-oriented_Fortran&amp;diff=733&amp;oldid=prev"/>
		<updated>2019-03-18T05:29:16Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;Revision as of 05:29, 18 March 2019&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l277&quot; &gt;Line 277:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 277:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* The class defines a .eq. operator for checking equality, as well as a custom .append. operator to concatenate strings.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* The class defines a .eq. operator for checking equality, as well as a custom .append. operator to concatenate strings.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* The functions made available by 'use sawlibf_string' are set to public. Since the 'length' function wasn't declared private in the class that is automatically exported. Also exported are the interfaces, so you can call .append. but not the implementation function appendString.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* The functions made available by 'use sawlibf_string' are set to public. Since the 'length' function wasn't declared private in the class that is automatically exported. Also exported are the interfaces, so you can call .append. but not the implementation function appendString.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;#160;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;#160;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[Category: Fortran]]&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>S.wales</name></author>
		
	</entry>
	<entry>
		<id>http://climate-cms.wikis.unsw.edu.au/index.php?title=Object-oriented_Fortran&amp;diff=272&amp;oldid=prev</id>
		<title>ScottWales: Imported from Wikispaces</title>
		<link rel="alternate" type="text/html" href="http://climate-cms.wikis.unsw.edu.au/index.php?title=Object-oriented_Fortran&amp;diff=272&amp;oldid=prev"/>
		<updated>2012-12-20T05:38:51Z</updated>

		<summary type="html">&lt;p&gt;Imported from Wikispaces&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;=Classes= &lt;br /&gt;
&lt;br /&gt;
Object classes are declared with the 'TYPE' keyword. This declares a class 'object' in the module 'cms_object':&lt;br /&gt;
&amp;lt;syntaxhighlight lang=fortran&amp;gt;&lt;br /&gt;
module cms_object&lt;br /&gt;
implicit none&lt;br /&gt;
    type object&lt;br /&gt;
        ! ...&lt;br /&gt;
    end type&lt;br /&gt;
end module&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To create an object of that class use 'TYPE()'&lt;br /&gt;
&amp;lt;syntaxhighlight lang=fortran&amp;gt;&lt;br /&gt;
program foo&lt;br /&gt;
    use cms_object, only: object&lt;br /&gt;
    type(object) :: bar&lt;br /&gt;
end program&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Member variables= &lt;br /&gt;
&lt;br /&gt;
Objects can have their own internal variables&lt;br /&gt;
&amp;lt;syntaxhighlight lang=fortran&amp;gt;&lt;br /&gt;
module cms_object&lt;br /&gt;
implicit none&lt;br /&gt;
    type object&lt;br /&gt;
        integer :: foo&lt;br /&gt;
        real(kind=8),dimension(:),allocatable :: bar&lt;br /&gt;
     end type&lt;br /&gt;
end module&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Variables are accessed using the '%' operator&lt;br /&gt;
&amp;lt;syntaxhighlight lang=fortran&amp;gt;&lt;br /&gt;
program foo&lt;br /&gt;
    use cms_object, only: object&lt;br /&gt;
    type(object) :: bar&lt;br /&gt;
&lt;br /&gt;
    bar%foo = 5&lt;br /&gt;
&lt;br /&gt;
    allocate(bar%bar(5))&lt;br /&gt;
    bar%bar(1) = 4.9&lt;br /&gt;
    deallocate(bar%bar)&lt;br /&gt;
end program&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Destructors= &lt;br /&gt;
&lt;br /&gt;
If an object has an 'ALLOCATABLE' variable that variable will need to be freed once you're done with it. This can be done automatically using a destructor, which will be run on the object when it goes out of scope (e.g. at the end of a function)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=fortran&amp;gt;&lt;br /&gt;
module cms_object&lt;br /&gt;
implicit none&lt;br /&gt;
    type object&lt;br /&gt;
       integer :: foo&lt;br /&gt;
       real(kind=8),dimension(:),allocatable :: bar&lt;br /&gt;
    contains&lt;br /&gt;
       final :: delete_object&lt;br /&gt;
    end type&lt;br /&gt;
contains&lt;br /&gt;
    subroutine delete_object(this)&lt;br /&gt;
        type(object) :: this&lt;br /&gt;
        if (allocated(this%bar)) then&lt;br /&gt;
            deallocate(this%bar)&lt;br /&gt;
        end if&lt;br /&gt;
    end subroutine&lt;br /&gt;
end module&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The destructor can be named anything you wish, although it will be helpful to have a unique name for each object's destructor once we get to inheritance. The destructor is run automatically like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=fortran&amp;gt;&lt;br /&gt;
program foo&lt;br /&gt;
    use cms_object, only: object&lt;br /&gt;
    type(object) :: bar&lt;br /&gt;
&lt;br /&gt;
    bar%foo = 5&lt;br /&gt;
&lt;br /&gt;
    allocate(bar%bar(5))&lt;br /&gt;
    bar%bar(1) = 4.9&lt;br /&gt;
&lt;br /&gt;
    ! bar is about to go out of scope at the end of the function&lt;br /&gt;
    ! The compiler automatically inserts 'call delete_object(bar)'&lt;br /&gt;
end program&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Constructors= &lt;br /&gt;
&lt;br /&gt;
Constructors are the opposite of destructors, they are run create an object. A constructor is a function or interface with the same name as the object's type&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=fortran&amp;gt;&lt;br /&gt;
module cms_object&lt;br /&gt;
implicit none&lt;br /&gt;
    type object&lt;br /&gt;
       integer :: foo&lt;br /&gt;
       real(kind=8),dimension(:),allocatable :: bar&lt;br /&gt;
    contains&lt;br /&gt;
       final :: delete_object&lt;br /&gt;
    end type&lt;br /&gt;
&lt;br /&gt;
    interface object&lt;br /&gt;
       procedure :: constructFromCount&lt;br /&gt;
       procedure :: constructFromArray&lt;br /&gt;
    end interface&lt;br /&gt;
contains&lt;br /&gt;
    subroutine delete_object(this)&lt;br /&gt;
        ! ...&lt;br /&gt;
    end subroutine&lt;br /&gt;
&lt;br /&gt;
    function constructFromCount(count) result(this)&lt;br /&gt;
        type(object) :: this&lt;br /&gt;
        integer, intent(in) :: count&lt;br /&gt;
        allocate(this%bar(count))&lt;br /&gt;
    end function&lt;br /&gt;
    function constructFromArray(array) result(this)&lt;br /&gt;
        type(object) :: this&lt;br /&gt;
        real(kind=8), dimension(:), intent(in) :: array&lt;br /&gt;
        allocate(this%bar(size(array)))&lt;br /&gt;
        this%bar = array&lt;br /&gt;
    end function&lt;br /&gt;
end module&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You call the constructor as if it were a function to initialise the object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=fortran&amp;gt;&lt;br /&gt;
program foo&lt;br /&gt;
    use cms_object, only: object&lt;br /&gt;
    type(object) :: bar&lt;br /&gt;
&lt;br /&gt;
    bar = object(5)&lt;br /&gt;
    write(*,*) size(bar%bar)&lt;br /&gt;
end program&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the array will be both created and destroyed automatically.&lt;br /&gt;
&lt;br /&gt;
=Object functions= &lt;br /&gt;
&lt;br /&gt;
You can add functions to an object by adding to its interface. When the function is called with the '%' operator the object to the left of the % will be passed as the function's first argument (similar to Python)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=fortran&amp;gt;&lt;br /&gt;
module cms_object&lt;br /&gt;
implicit none&lt;br /&gt;
    type object&lt;br /&gt;
       integer :: foo&lt;br /&gt;
       real(kind=8),dimension(:),allocatable :: bar&lt;br /&gt;
    contains&lt;br /&gt;
       final :: delete_object&lt;br /&gt;
       procedure :: increment&lt;br /&gt;
    end type&lt;br /&gt;
&lt;br /&gt;
    interface object&lt;br /&gt;
       procedure :: constructFromCount&lt;br /&gt;
       procedure :: constructFromArray&lt;br /&gt;
    end interface&lt;br /&gt;
contains&lt;br /&gt;
    ! ...&lt;br /&gt;
&lt;br /&gt;
    subroutine increment(this, value)&lt;br /&gt;
        type(object) :: this&lt;br /&gt;
        integer :: value&lt;br /&gt;
&lt;br /&gt;
        this%bar = this%bar + 1&lt;br /&gt;
    end subroutine&lt;br /&gt;
end module&lt;br /&gt;
&lt;br /&gt;
program foo&lt;br /&gt;
    use cms_object&lt;br /&gt;
    type(object) :: bar&lt;br /&gt;
&lt;br /&gt;
    bar = object(5)&lt;br /&gt;
&lt;br /&gt;
    ! Really runs 'call increment(bar,2)'&lt;br /&gt;
    call bar%increment(2)&lt;br /&gt;
end program&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Assignment operator= &lt;br /&gt;
&lt;br /&gt;
If you want to be able to convert between types you can define assignment operators for the class. You will also need to define a custom assignment if the class contains allocatable arrays. These are defined in a module interface&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=fortran&amp;gt;&lt;br /&gt;
module cms_object&lt;br /&gt;
implicit none&lt;br /&gt;
    type object&lt;br /&gt;
        ! ...&lt;br /&gt;
    end type&lt;br /&gt;
    ! ...&lt;br /&gt;
    interface assignment(=)&lt;br /&gt;
        procedure :: assignFromObject&lt;br /&gt;
        procedure :: assignFromArray&lt;br /&gt;
    end interface&lt;br /&gt;
contains&lt;br /&gt;
    ! ...&lt;br /&gt;
    subroutine assignFromObject(this,other)&lt;br /&gt;
        class(object),intent(inout) :: this&lt;br /&gt;
        class(object),intent(in) :: other&lt;br /&gt;
        allocate(this%bar(size(other%bar)))&lt;br /&gt;
        this%foo = other%foo&lt;br /&gt;
        this%bar = other%bar&lt;br /&gt;
    end subroutine&lt;br /&gt;
    subroutine assignFromArray(this,other)&lt;br /&gt;
        class(object),intent(inout) :: this&lt;br /&gt;
        real(kind=8),dimension(:),intent(in) :: other&lt;br /&gt;
        allocate(this%bar(size(other)))&lt;br /&gt;
        this%foo = 12&lt;br /&gt;
        this%bar = other&lt;br /&gt;
    end subroutine&lt;br /&gt;
end module&lt;br /&gt;
program foo&lt;br /&gt;
    use cms_object&lt;br /&gt;
    type(object) :: a,b,c&lt;br /&gt;
    real(kind=8),dimension(5) array&lt;br /&gt;
&lt;br /&gt;
    a = object(5)&lt;br /&gt;
    b = a&lt;br /&gt;
    c = array&lt;br /&gt;
end program&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Other operators= &lt;br /&gt;
&lt;br /&gt;
You can also define operators that work on your class, either normal ones like .not., .and. &amp;amp;c or your own custom ones. To do this you add an operator interface to the module&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=fortran&amp;gt;&lt;br /&gt;
module cms_object&lt;br /&gt;
implicit none&lt;br /&gt;
    type object&lt;br /&gt;
        ! ...&lt;br /&gt;
    end type&lt;br /&gt;
    ! ...&lt;br /&gt;
    interface operator(.eq.)&lt;br /&gt;
        procedure :: equalsObject&lt;br /&gt;
    end interface&lt;br /&gt;
    interface operator(.foo.)&lt;br /&gt;
        procedure :: fooObject&lt;br /&gt;
    end interface&lt;br /&gt;
contains&lt;br /&gt;
    ! ...&lt;br /&gt;
    function equalsObject(lhs,rhs) return(equal)&lt;br /&gt;
        type(object), intent(in) :: lhs,rhs&lt;br /&gt;
        logical :: equal&lt;br /&gt;
        equal = (lhs%foo .eq. rhs%foo) .and. (lhs%bar .eq. rhs%bar)&lt;br /&gt;
    end function&lt;br /&gt;
    function fooObject(rhs) return(foo)&lt;br /&gt;
        type(object),intent(in) :: rhs&lt;br /&gt;
        integer :: foo&lt;br /&gt;
        foo = rhs%foo&lt;br /&gt;
    end function&lt;br /&gt;
end module&lt;br /&gt;
program foo&lt;br /&gt;
    use cms_object&lt;br /&gt;
    type(object) :: a,b&lt;br /&gt;
    logical :: equal&lt;br /&gt;
    integer :: foo&lt;br /&gt;
&lt;br /&gt;
    equal = a .eq. b&lt;br /&gt;
    foo = .foo. b&lt;br /&gt;
end program&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Operators can either be unary (like .not.) or binary (like .and.). The number of arguments to the function decides which it is.&lt;br /&gt;
&lt;br /&gt;
= Full Example =&lt;br /&gt;
&lt;br /&gt;
You can find an example of a full object [https://github.com/ScottWales/sawlibf/blob/master/src/lib/sawlibf/string.f90 | here]. It provides a 'string' class, which handles automatic allocation and deallocation of character strings, as well as some utilities for converting between strings and character arrays.&lt;br /&gt;
&lt;br /&gt;
Some things to note:&lt;br /&gt;
&lt;br /&gt;
* The module name is prepended with the name of the library it is part of. This helps to avoid name collisions between different libaries&lt;br /&gt;
* The default access level for the module is private, meaning functions cannot be called directly unless that's explicitly permitted. This is handy when there's a lot of interface functions, you can allow calling the interfaces by prohibit calling the actual implementation functions directly, again tidying up the namespace.&lt;br /&gt;
* The member variables of the class are private. This way the implementation details can be changed without having to change external code, for instance if you wanted to make identical strings use the same memory.&lt;br /&gt;
* The length variable is accessible through a member function, however the character data isn't, again so the memory layout could be changed easily. The only way to get the character data is through assigning the string to a character(len=*).&lt;br /&gt;
* The class uses dynamic memory, so contains a destructor and assignment operator&lt;br /&gt;
* Most of the class functions can use strings and character(*) interchangeably through the use of interfaces&lt;br /&gt;
* The class defines a .eq. operator for checking equality, as well as a custom .append. operator to concatenate strings.&lt;br /&gt;
* The functions made available by 'use sawlibf_string' are set to public. Since the 'length' function wasn't declared private in the class that is automatically exported. Also exported are the interfaces, so you can call .append. but not the implementation function appendString.&lt;/div&gt;</summary>
		<author><name>ScottWales</name></author>
		
	</entry>
</feed>