Object-oriented programming Spice supports object-oriented programming in the form of composition. That means that types can be composed via structs, interfaces and methods.
Example scenario You need to model three different kinds of objects: humans, cars and parrots. Therefore, you create three structs with the respective names:
Spice type Human struct {
string firstName
string lastName
unsigned int age
}
type Car struct {
string brand
string model
unsigned int seats
}
type Parrot struct {
string name
unsigned int age
}
Now, as you have a speaking parrot, you want to give the parrot and the human the ability to speak. In addition to that, all three objects can make sounds. The recommended way of doing this, is to use interfaces like this:
Spice type Speak interface {
p sayHello ( string );
}
type MakeSound interface {
p makeSound ();
}
type Human struct : MakeSound , Speak {
string firstName
string lastName
unsigned int age
}
p Human . ctor ( string firstName , string lastName , unsigned int age ) {
this . firstName = firstName ;
this . lastName = lastName ;
this . age = age ;
}
p Human . makeSound () {
printf ( "Sigh...\n" );
}
p Human . sayHello ( string name ) {
printf ( "Hi, %s!\n" , name );
}
type Car struct : MakeSound {
string brand
string model
unsigned int seats
}
p Car . ctor ( string brand , string model , unsigned int seats ) {
this . brand = brand ;
this . model = model ;
this . seats = seats ;
}
p Car . makeSound () {
printf ( "Wroom, wroom!\n" );
}
type Parrot struct : MakeSound , Speak {
string name
unsigned int age
}
p Parrot . ctor ( string name , unsigned int age ) {
this . name = name ;
this . age = age ;
}
p Parrot . makeSound () {
printf ( "Sqawk!\n" );
}
p Parrot . sayHello ( string name ) {
printf ( "Hello %s, squawk!\n" , name );
}
f < int > main () {
Human human = Human ( "John" , "Doe" , 25 );
Car car = Car ( "Toyota" , "Corolla" , 5 );
Parrot parrot = Parrot ( "Polly" , 3 );
human . makeSound ();
car . makeSound ();
parrot . makeSound ();
human . sayHello ( "Jane" );
parrot . sayHello ( "Jane" );
return 0 ;
}
All living beings, parrots and humans have an age. So you might want to extract the unsigned int age
, that exists in both structs to a separate struct called LivingBeing
.
Spice // ...
type LivingBeing struct {
unsigned int age
}
type Human struct : MakeSound , Speak {
compose LivingBeing livingBeing
string firstName
string lastName
}
type Parrot struct : MakeSound , Speak {
compose LivingBeing livingBeing
string name
}
// ...
The compose
keyword is used to include the fields and methods of another struct into the current struct. The members of the parent struct are accessible directly via name. e.g. parrot.age
or through the compose member itself, e.g. parrot.livingBeing.age
.