Emulating Object-Oriented Programming with Structs and Methods

Explore how to emulate object-oriented programming in Julia using structs and methods, focusing on defining mutable and immutable structs, associating methods, and emulating inheritance and interfaces.

4.4 Emulating Object-Oriented Programming with Structs and Methods

In the world of software development, object-oriented programming (OOP) has long been a popular paradigm, offering a way to structure code that models real-world entities. While Julia is not inherently an object-oriented language, it provides powerful features that allow developers to emulate OOP concepts effectively. In this section, we will explore how to use Julia’s structs and methods to achieve this, focusing on defining structs, associating methods, and emulating inheritance and interfaces.

Defining Structs

In Julia, structs are used to define composite data types. They are similar to classes in object-oriented languages but come with some differences. Julia offers two types of structs: mutable and immutable.

Mutable and Immutable Structs

Immutable Structs: These are the default in Julia and are defined using the struct keyword. Once an instance of an immutable struct is created, its fields cannot be changed. This immutability can lead to performance optimizations, as the compiler can make certain assumptions about the data.

1struct Point
2    x::Float64
3    y::Float64
4end
5
6p = Point(1.0, 2.0)
7
8println("x: ", p.x, ", y: ", p.y)

Mutable Structs: If you need to change the fields of a struct after it has been created, you can define a mutable struct using the mutable struct keyword.

 1mutable struct MutablePoint
 2    x::Float64
 3    y::Float64
 4end
 5
 6mp = MutablePoint(1.0, 2.0)
 7
 8mp.x = 3.0
 9mp.y = 4.0
10
11println("x: ", mp.x, ", y: ", mp.y)

Associating Methods

In Julia, methods are functions that can operate on structs. Unlike traditional OOP languages where methods are defined within classes, Julia separates data (structs) from behavior (methods). This separation allows for more flexible and powerful programming patterns.

Implementing Methods that Operate on Structs

To associate methods with a struct, you define functions that take instances of the struct as arguments. This approach leverages Julia’s multiple dispatch feature, allowing you to define different behaviors for functions based on the types of their arguments.

1function distance(p::Point)
2    return sqrt(p.x^2 + p.y^2)
3end
4
5p = Point(3.0, 4.0)
6println("Distance from origin: ", distance(p))

Multiple Dispatch: This feature allows you to define multiple methods for the same function name, each with different argument types. It is a powerful tool for creating flexible and reusable code.

1function distance(p1::Point, p2::Point)
2    return sqrt((p2.x - p1.x)^2 + (p2.y - p1.y)^2)
3end
4
5p1 = Point(1.0, 2.0)
6p2 = Point(4.0, 6.0)
7println("Distance between points: ", distance(p1, p2))

Inheritance and Interfaces

While Julia does not support inheritance in the traditional OOP sense, it provides mechanisms to achieve similar functionality through abstract types and composition.

Using Abstract Types

Abstract types in Julia allow you to define a hierarchy of types without specifying their implementation. They serve as a blueprint for concrete types (structs) that inherit from them.

 1abstract type Shape end
 2
 3struct Circle <: Shape
 4    radius::Float64
 5end
 6
 7struct Rectangle <: Shape
 8    width::Float64
 9    height::Float64
10end

Emulating Inheritance with Composition

Composition is a design principle where a struct contains instances of other structs, allowing you to build complex types from simpler ones. This approach is often preferred over inheritance as it promotes flexibility and reusability.

 1struct Wheel
 2    radius::Float64
 3end
 4
 5struct Car
 6    wheels::Vector{Wheel}
 7    color::String
 8end
 9
10wheels = [Wheel(15.0), Wheel(15.0), Wheel(15.0), Wheel(15.0)]
11car = Car(wheels, "Red")

Interfaces in Julia

Interfaces in Julia are not explicitly defined like in some other languages. Instead, they are a set of functions that a type must implement to be considered as implementing the interface. This is often documented as a convention.

 1function draw(obj)
 2    error("draw not implemented for $(typeof(obj))")
 3end
 4
 5function draw(c::Circle)
 6    println("Drawing a circle with radius ", c.radius)
 7end
 8
 9function draw(r::Rectangle)
10    println("Drawing a rectangle with width ", r.width, " and height ", r.height)
11end
12
13c = Circle(5.0)
14r = Rectangle(4.0, 3.0)
15draw(c)
16draw(r)

Visualizing Structs and Methods in Julia

To better understand how structs and methods work together in Julia, let’s visualize the relationship using a class diagram.

    classDiagram
	    class Shape {
	        <<abstract>>
	    }
	    class Circle {
	        radius: Float64
	    }
	    class Rectangle {
	        width: Float64
	        height: Float64
	    }
	    Shape <|-- Circle
	    Shape <|-- Rectangle
	    class Car {
	        wheels: Vector~Wheel~
	        color: String
	    }
	    class Wheel {
	        radius: Float64
	    }
	    Car o-- Wheel

Diagram Description: This diagram illustrates the relationship between the abstract type Shape and its concrete implementations Circle and Rectangle. It also shows the composition relationship between Car and Wheel.

Try It Yourself

To deepen your understanding, try modifying the code examples above:

  • Add a new struct Triangle that implements the Shape interface.
  • Define a method area for each shape that calculates its area.
  • Create a new struct Bicycle that uses composition with Wheel.

Key Takeaways

  • Structs in Julia are used to define composite data types and can be mutable or immutable.
  • Methods are functions that operate on structs, leveraging Julia’s multiple dispatch for flexibility.
  • Abstract Types and Composition are used to emulate inheritance and interfaces, promoting code reusability and flexibility.

References and Further Reading

Remember, this is just the beginning. As you progress, you’ll build more complex and interactive applications. Keep experimenting, stay curious, and enjoy the journey!

Quiz Time!

Loading quiz…
Revised on Thursday, April 23, 2026