Day 6: Composite Types

I’ve had a look at the basic data types available in Julia as well as how these can be stashed in collections. What about customised-composite-DIY-build-your-own style types?

Composite types are declared with the type keyword. To illustrate we’ll declare a type for storing geographic locations, with attributes for latitude, longitude and altitude. The type immediately has two methods: a default constructor and a constructor specialised for arguments with data types corresponding to those of the type’s attributes. More information on constructors can be found in the documentation.

type GeographicLocation
  latitude::Float64
  longitude::Float64
  altitude::Float64
end
methods(GeographicLocation)
# 2 methods for generic function "GeographicLocation":
GeographicLocation(latitude::Float64,longitude::Float64,altitude::Float64)
GeographicLocation(latitude,longitude,altitude)

Creating instances of this new type is simply a matter of calling the constructor. The second instance below clones the type of the first instance. I don’t believe I’ve seen that being done with another language. (That’s not to say that it’s not possible elsewhere! I just haven’t seen it.)

g1 = GeographicLocation(-30, 30, 15)
GeographicLocation(-30.0,30.0,15.0)
typeof(g1) # Interrogate type
GeographicLocation (constructor with 3 methods)
g2 = typeof(g1)(5, 25, 165) # Create another object of the same type.
GeographicLocation(5.0,25.0,165.0)

We can list, access and modify instance attributes.

names(g1)
3-element Array{Symbol,1}:
 :latitude
 :longitude
 :altitude
g1.latitude
-30.0
g1.longitude
30.0
g1.latitude = -25 # Attributes are mutable
-25.0

Additional “outer” constructors can provide alternative ways to instantiate the type.

GeographicLocation(lat::Real, lon::Real) = GeographicLocation(lat, lon, 0)
GeographicLocation (constructor with 3 methods)
g3 = GeographicLocation(-30, 30)
GeographicLocation(-30.0,30.0,0.0)

Of course, we can have collections of composite types. In fact, these composite types have essentially all of the rights and privileges of the built in types.

locations = [g1, g2, g3]
3-element Array{GeographicLocation,1}:
 GeographicLocation(-25.0,30.0,15.0)
 GeographicLocation(5.0,25.0,165.0)
 GeographicLocation(-30.0,30.0,0.0)

The GeographicLocation type declared above is a “concrete” type because it has attributes and can be instantiated. You cannot derive subtypes from a concrete type. You can, however, declare an abstract type which acts as a place holder in the type hierarchy. As opposed to concrete types, an abstract type cannot be instantiated but it can have subtypes.

abstract Mammal
type Cow <: Mammal
end
Mammal() # You can't instantiate an abstract type!
ERROR: type cannot be constructed
Cow()
Cow()

The immutable keyword will create a type where the attributes cannot be modified after instantiation.

Additional ramblings and examples of composite types can be found on GitHub. Also I’ve just received an advance copy of Julia in Action by Chris von Csefalvay which I’ll be reviewing over the next week or so.

Cover of 'Learn Julia'.