2025-01-12
There are two types of programming languages: Statically typed systems such as C++, where each variable must be of a particular type before execution, and dynamically typed systems, where the type is not known until runtime. Julia is a dynamically typed language, but still has the ability to specify certain types for better efficiency.
Types in Julia are organised in a hierarchy, which is very similar to inheritance in object-oriented languages such as C++, except that it also works for primitive types. Each type has exactly one parent type and possibly several child types, which can be determined using the supertype
and subtype
cmmands.
This way we can display the complete type tree:
Types in Julia.
Figure was created with app.diagrams.net and is hereby licensed under Public Domain (CC0)
As you can see, each type is a subtype of the type Any
. We can check whether a type is a subtype of another using the <: operator.
Concrete types such as Float64 or Int64 can be instantiated, whereas abstract types exist only in the type hierarchy.
There are also composite types, which are made up of many smaller types.
Important
Composite types in Julia are not the same as classes in other languages. They don’t support inheritance and can’t have member functions.
To instantiate a variable of that type, we call it’s constructor.
julia> author = Person("Marcel", 29, false)
Person("Marcel", 29, false)
julia> typeof(author)
Person
As usual, we can access the member variables of a composite type using the . notation.
By default, composite types are immutable, meaning they cannot be changed. However, an immutable object can contain mutable fields, such as arrays, which remain mutable.
To define a mutable type, use the mutable
keyword. If you want to ensure that a particular field remains constant in an otherwise mutable object, you can do this using the const
keyword.
TODO: Ist das wichtig?
Abstract, primitive and composite types are all instances of the same concept, DataType
, which is the type of these types.
What if you want to specify that a function accepts signed and unsigned integers, but not bool? You can use a union type.
The concept is similar in other programming languages.
A particularly useful case of a Union type is Union{T, Nothing}
, which would be equivalent to std::optional
in C++.
Types in Julia can take parameters, so type declarations introduce a whole family of types. This concept is known in other programming languages as generic programming.
In other words, Julia’s type parameters are invariant.
Let’s say we want to write a generic function that can take Point{Float64}
as an argument. The following method won’t work:
Since Point{Float64}
is not a subtype of Point{Real}
, the function can’t take Point{Float64}
as an argument.
The correct way to define a method that accepts all arguments of type Point{T}
where T
is a subtype of Real
is:
Alternatively, one could also write
sdf