Outlines

Objects

It’s finally time to find out what all the @ symbols we’ve been using mean. We’ve seen @ being used a few times so far, in expressions like ciorcal@stáitse and slánuimh_rand@mata. To find out what it means, we have to talk about objects.

What are they?

Objects can be thought of as a collection of values. An object can contain anything we want, numbers, text, actions etc. Each member of the object has a name, much like how variables have names.

For example we could have an object that represents a person. That object could have members called age, address or favourite_colour that store the persons age, address or favourite colour.

Objects can also have special behaviours that make them more useful to us, but we’ll see more on that soon.

How do we use objects? To do that we have to use the “@symbol.

What is “@”?

When we want to access a member of an object, we use its name and the “@” symbol to do that. The syntax is:

<member name>@<object>

Let’s say we have an object in a variable called tree, and it has a member called height that contains its height. We would write height@tree to access it.

When we write ciorcal@stáitse we are saying “Get the value with the name ciorcal from the stáitse object.”, then we can call the action as normal (e.g. ciorcal@stáitse(200, 200, 100)).

We can split the expression ciorcal@stáitse(200, 200, 100) into two steps to see this more clearly. The first step will be getting the ciorcal action, and the second will be calling the action.

First we can use ciorcal@stáitse to get the ciorcal action, then we can save it in a variable, let’s call that variable gníomh_ciorcal.

gníomh_ciorcal := ciorcal@stáitse

Now we can call that action as before by writing:

gníomh_ciorcal := ciorcal@stáitse
gníomh_ciorcal(200, 200, 100)

Try it out to see that it works!:

Creation

We make an object by first creating something called an outline. Then we can use the outline to create objects. One outline can be used to create several objects.

For example, we can make an outline for an object that represents a person, then we can create a whole family of people by creating person objects from that outline.

Outlines

An outline is exactly what it sounds like, it’s an outline of the structure of an object. When we make an outline we define the name of the outline, and a list of actions that define the objects behaviour.

We use the creatlach keyword to make an outline, “creatlach” is the Irish for “outline” (or “skeleton”). The syntax to make an outline is as follows:

creatlach <outline-name> {
    <list of actions>
    ...
}

For example, here’s how we would create an outline called Simplí that has no special behaviour. “Simplí” translates as “simple”.

>-- New outline with no actions
creatlach Simplí {
}

This creates a new action called Simplí. When you call Simplí, it will create an object from the Simplí outline and return it.

We can then make an object from the “Simplí” outline by calling Simplí like so:

>-- New outline with no actions
creatlach Simplí {
}

>-- Create an object from the Simplí outline
oibiacht_simplí := Simplí()

We created a new variable called “oibiacht_simplí” to store the object. “oibiacht simplí” means “simple object”. This object is exactly as it sounds, simple. It doesn’t have any members yet. Let’s add a member called “ball” (meaning “member”) now with the value "Ár mball nua" (“Our new member”). The syntax is just like updating a variable:

>-- New outline with no actions
creatlach Simplí {
}

>-- Create an object from the Simplí outline
oibiacht_simplí := Simplí()

>-- Add a new member to oibiacht_simplí
ball@oibiacht_simplí = "Ár mball nua"

Now we can use ball@oibiacht_simplí to access the value we stored in that member.

>-- New outline with no actions
creatlach Simplí {
}

>-- Create an object from the Simplí outline
oibiacht_simplí := Simplí()

>-- Add a new member to oibiacht_simplí
ball@oibiacht_simplí = "Ár mball nua"

>-- Access the member and write
scríobh(ball@oibiacht_simplí)

Try it out!

Challenge

Fill in the following code so that it prints “My age is <your age>”. e.g. “My age is 18”.

Click here to see the solution

Why Objects?

At this point you might be thinking “Why do we need objects? They seem just like variables”. Lets take a look at a quick example of why objects are useful.

The setup is this: We want to write a program that will draw a square, print its area and its perimeter.

To start, let’s make an empty outline called Ciorcal, and make an action called déan_ciorcal that will create an empty object, and fill in some details. We want to record the x-coordinate, y-coordinate, radius and colour of our circle. We’ll put these in members called x, y, ga and dath.

>-- Empty outline definition
creatlach Ciorcal {
}

>-- Action to make a circle object with x, y, radius and colour
gníomh déan_ciorcal(x, y, ga, dath) {
    >-- Create blank circle
    c := Ciorcal()

    >-- Set our parameters
    x@c = x
    y@c = y
    ga@c = ga
    dath@c = dath

    >-- Return the circle
    toradh c
}

Now we can create three actions, one to draw the circle, one to get the area, and one to get the perimeter. We’ll call these actions tarraing, achar and imlíne. Each of these actions only needs to take one parameter, the circle.

>-- Draw the circle
gníomh tarraing(ciorc) {
    >-- Set the colour
    dath@stáitse(dath@ciorc)

    >-- Draw the circle
    ciorcal@stáitse(x@ciorc, y@ciorc, ga@ciorc)
}

>-- Return the area, area = pi * r^2
gníomh achar(ciorc) {
    toradh pi@mata * ga@ciorc * ga@ciorc
}

>-- Return the perimeter, perimeter = 2 * pi * r
gníomh imlíne(ciorc) {
    toradh 2 * pi@mata * ga@ciorc
}

Now we can use our déan_ciorcal action to create a circle, and our three other actions to draw it, print the area and print the perimeter.

c := déan_ciorcal(100, 100, 50, "dearg")
tarraing(c)
scríobh("Area is:", achar(c))
scríobh("Perimeter is:", imlíne(c))

Try out the whole program! Switch to the console to see the text output.

Behaviour

This is nice pattern, but it’s messy. Can we write this in a nicer way?

This is where outline actions come in, we can move our actions like “tarraing”, “imlíne” and “achar” into the definition of the outline.

To do this we use the keyword “seo”, which means “this”. The “seo” keyword has a special function, when we use it in an outline action, it refers to whatever object made from that outline is calling the action.

When we create an object from an outline, that object is called an instance of that outline. When we use the seo keyword in a outline action, it refers to whatever instance of the outline is being used to call the action.

This is easier to see in practice. Let’s change our “tarraing” action into an outline action. First let’s copy the action as-is into the outline definition. Our outline definition looks like this now:

creatlach Ciorcal {

    >-- Draw the circle
    gníomh tarraing(ciorc) {
        >-- Set the colour
        dath@stáitse(dath@ciorc)

        >-- Draw the circle
        ciorcal@stáitse(x@ciorc, y@ciorc, ga@ciorc)
    }
}

Now we can get rid of the ciorc argument and we can use the “seo” keyword instead.

creatlach Ciorcal {

    >-- Draw the circle
    gníomh tarraing() {
        >-- Set the colour
        dath@stáitse(dath@seo)

        >-- Draw the circle
        ciorcal@stáitse(x@seo, y@seo, ga@seo)
    }
}

Previously when we wanted to call tarraing with a particular circle object c, we would write tarraing(c). Now that tarraing is an outline action, we can write tarraing@c() to call it.

When we do this, because c is an instance of Ciorcal, everywhere we used seo, it will point to c.

Let’s turn “achar” and “imlíne” into outline actions too. We move them into the outline definition, get rid of the “ciorcargument, and use seo instead.

creatlach Ciorcal {

    >-- Draw the circle
    gníomh tarraing() {
        >-- Set the colour
        dath@stáitse(dath@seo)

        >-- Draw the circle
        ciorcal@stáitse(x@seo, y@seo, ga@seo)
    }

    >-- Return the area, area = pi * r^2
    gníomh achar() {
        toradh pi@mata * ga@seo * ga@seo
    }

    >-- Return the perimeter, perimeter = 2 * pi * r
    gníomh imlíne() {
        toradh 2 * pi@mata * ga@seo
    }
}

Now we can replace our calls to “achar” and “imlíne” with this:

c := déan_ciorcal(100, 100, 50, "dearg")
tarraing@c()
scríobh("Area is:", achar@c())
scríobh("Perimeter is:", imlíne@c())

achar, imlíne and draw are all outline actions, so Setanta will make the seo keyword point to c, because it is an instance of Ciorcal.

Try it out!:

Constructor

Outline actions are useful, but can we get rid of the need for the déan_ciorcal action?

Yes we can! Setanta let’s you create a special outline action called a constructor. A constructor is an action that is called when an object is made from the outline.

To make a constructor, you create an outline action with the name “nua”, which means “new”. Then when you create an object from that outline, the arguments you use are passed into the constructor action.

Quick Example

Let’s see a quick example, we’ll make an outline called Person, and give it a constructor that takes one argument, name.

creatlach Person {
    gníomh nua(name) {
    }
}

Let’s add code into the constructor to write the name that’s passed in:

creatlach Person {
    gníomh nua(name) {
        scríobh("Created a person called", name)
    }
}

Now when we create a new person, you can pass in the name you want:

creatlach Person {
    gníomh nua(name) {
        scríobh("Created a person called", name)
    }
}

me := Person("Eoin")

Try it out! You’ll see that "Created a person called Eoin" is written on the console.

Ciorcal Constructor

Now we can get rid of our déan_ciorcal action, and use a constructor instead. Let’s create our constructor that takes the same arguments, x, y, ga and dath. We can use the seo keyword to store those arguments in the instance we are creating

gníomh nua(x, y, ga, dath) {
    x@seo = x
    y@seo = y
    ga@seo = ga
    dath@seo = dath
}

Now we can totally get rid of the déan_ciorcal action, and instead of creating c by writing:

c := déan_ciorcal(100, 100, 50, "dearg")

we can write:

c := Ciorcal(100, 100, 50, "dearg")

Our final program looks like this:

creatlach Ciorcal {

    gníomh nua(x, y, ga, dath) {
        x@seo = x
        y@seo = y
        ga@seo = ga
        dath@seo = dath
    }

    >-- Draw the circle
    gníomh tarraing() {
        >-- Set the colour
        dath@stáitse(dath@seo)

        >-- Draw the circle
        ciorcal@stáitse(x@seo, y@seo, ga@seo)
    }

    >-- Return the area, area = pi * r^2
    gníomh achar() {
        toradh pi@mata * ga@seo * ga@seo
    }

    >-- Return the perimeter, perimeter = 2 * pi * r
    gníomh imlíne() {
        toradh 2 * pi@mata * ga@seo
    }
}

c := Ciorcal(100, 100, 50, "dearg")
tarraing@c()
scríobh("Area is:", achar@c())
scríobh("Perimeter is:", imlíne@c())

Let’s give it a try!