ONE SPACESUIT EXTENDING ANOTHER

Once you have written a spacesuit, you will often want a second one that is almost the same. A dog is a pet with tricks. A savings jar is a piggy bank that pays interest. satellite lets one spacesuit extend another: the new one gets everything the old one has, and adds its own. This post also shows how to keep one spacesuit inside another. If spacesuits are new to you, start with SPACESUITS: SATELLITE OBJECTS.

Extending: name the other spacesuit in the brackets

The brackets after a spacesuit’s name have been empty so far. Put the name of another spacesuit there, and the new one extends it: satellite.spacesuit dog(pet) says a dog is a pet, plus more.

A dog object then has everything a pet has:

  • the pet’s fields, as well as its own. The dog’s capsules use the pet’s fields by their bare names, as call_tricks uses name below.
  • the pet’s capsules. The dog’s capsules call them by their bare names, and a program calls the public ones on a dog object.
  • every constructor. The pet’s constructor runs first and the dog’s after it. The arguments you give when making the object go to the nearest constructor: the dog’s here, or the pet’s if the dog had none of its own.

A capsule the dog declares again replaces the pet’s for every dog. Here the dog replaces call_sound:

pets.satlSATELLITE 004 Download
A dog extends a pet and replaces one of its capsules
satellite.include(satellite)

satellite.spacesuit pet()
{
    satellite.protected
    {
        satellite.variable.string name = "a pet"
    }

    satellite.constructor()
    {
        satellite.console.display("pet's constructor")
    }

    satellite.public
    {
        satellite.capsule call_sound()
        {
            satellite.return("...")
        }

        satellite.capsule describe()
        {
            satellite.return(name + " says " + call_sound())
        }

        satellite.capsule set_name(satellite.variable.string given)
        {
            name = given
        }
    }
}

satellite.spacesuit dog(pet)
{
    satellite.protected
    {
        satellite.variable.number tricks = 0
    }

    satellite.constructor(satellite.variable.number tricks_input)
    {
        satellite.console.display("dog's constructor")
        tricks = tricks_input
    }

    satellite.public
    {
        satellite.capsule call_sound()
        {
            satellite.return("woof")
        }

        satellite.capsule call_tricks()
        {
            satellite.return(name + " knows " + tricks.to_string() + " tricks")
        }
    }
}

satellite.capsule introduce(pet any)
{
    satellite.console.display(any.describe())
}

satellite.capsule satellite.main()
{
    dog rex(3)
    rex.set_name("rex")
    satellite.console.display(rex.call_tricks())
    introduce(rex)

    pet goldfish
    introduce(goldfish)
    satellite.return(satellite)
}
OUTPUT
pet's constructor
dog's constructor
rex knows 3 tricks
rex says woof
pet's constructor
a pet says ...

Follow what happened:

  1. dog rex(3) ran the pet’s constructor, then the dog’s, which was handed the 3.
  2. rex.set_name("rex") is a pet capsule, called on a dog.
  3. introduce takes a pet, and a dog is a pet, so introduce(rex) is allowed.
  4. Inside it, the pet’s describe calls call_sound(), and because rex is a dog, the dog’s replacement runs: “woof”. The plain pet goldfish still says “…”.

A name declared as the older spacesuit can hold an object of the newer one: pet any held a dog. That is what lets one capsule work for every kind of pet.

A replacement must be called the same way

Because a pet name may hold a dog, a capsule that replaces another must take the same arguments and be just as reachable. It cannot move from satellite.public to satellite.protected, for example. satl checks this before anything runs:

cat.satlSATELLITE 004 Download
A replacement that takes different arguments is refused
satellite.include(satellite)

satellite.spacesuit pet()
{
    satellite.public
    {
        satellite.capsule call_sound()
        {
            satellite.return("...")
        }
    }
}

satellite.spacesuit cat(pet)
{
    satellite.public
    {
        satellite.capsule call_sound(satellite.variable.number times)
        {
            satellite.return("meow")
        }
    }
}

satellite.capsule satellite.main()
{
    cat tom
    satellite.return(satellite)
}
OUTPUT
--------------------------------------------------------------------------------
SATELLITE CRITICAL ERROR REPORT
--------------------------------------------------------------------------------
S110: LINE_NOT_UNDERSTOOD
satl(check): cat's call_sound replaces pet's for its objects, and it takes
different arguments from the one it replaces -- a name declared pet may hold one
of them, so the two must be called the same way

directory: cat.satl:18
syntax: satellite.capsule call_sound(satellite.variable.number times)
        /\

satellite has no scenario for this line -- it is spelled in a shape the language
does not have a meaning for.
machine code 13 satl_line_not_understood -- satl exits with this.

--------------------------------------------------------------------------------

A spacesuit extends one other spacesuit, or none. Two names in the brackets are refused, and so is a circle, where following the brackets leads back to where you started.

A spacesuit inside a spacesuit

A spacesuit can also hold whole spacesuits of its own, written in its satellite.public or satellite.protected section. This suits a type that only makes sense as part of another, like the rooms of a house.

  • Inside the outer spacesuit, the inner one is named bare: room.
  • From outside, a public inner spacesuit is house.room. A protected one cannot be named from outside at all.
  • The inner spacesuit’s capsules see its own fields, not the outer one’s.
house.satlSATELLITE 004 Download
A house holds rooms, and room is a spacesuit inside house
satellite.include(satellite)

satellite.spacesuit house()
{
    satellite.protected
    {
        satellite.variable.string street = ""
        satellite.container.list<room> rooms = {}
    }

    satellite.constructor(satellite.variable.string street_input)
    {
        street = street_input
    }

    satellite.public
    {
        satellite.spacesuit room()
        {
            satellite.protected
            {
                satellite.variable.string name = ""
                satellite.variable.number size = 0
            }

            satellite.constructor(satellite.variable.string name_input, satellite.variable.number size_input)
            {
                name = name_input
                size = size_input
            }

            satellite.public
            {
                satellite.capsule call_line()
                {
                    satellite.return(name + ", " + size.to_string() + " square metres")
                }
            }
        }

        satellite.capsule add_room(room given)
        {
            rooms.append(given)
        }

        satellite.capsule build_kitchen()
        {
            room kitchen("kitchen", 12)
            rooms.append(kitchen)
        }

        satellite.capsule show()
        {
            satellite.console.display(street + " has " + rooms.size.to_string() + " rooms")
            satellite.statement.for(satellite.variable.number i = 1; i <= rooms.size; i++)
            {
                satellite.console.display("- " + rooms[i].call_line())
            }
        }
    }
}

satellite.capsule satellite.main()
{
    house home("1 Orbit Lane")
    house.room lounge("lounge", 20)
    home.add_room(lounge)
    home.build_kitchen()
    home.show()
    satellite.return(satellite)
}
OUTPUT
1 Orbit Lane has 2 rooms
- lounge, 20 square metres
- kitchen, 12 square metres

The program made the lounge from outside, as house.room, and handed it in. The house made its own kitchen, as plain room. Both ended up in the same list, satellite.container.list<room>.

Where next

The FULL REFERENCE lists every spacesuit word and every rule satl checks. To keep your spacesuits in files of their own and reach them from a program, see INCLUDING FILES AND NAMESPACES.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *