Chapter 7. Classes and OOP
Classes are a way of storing and organizing subclasses, functions, properties, and traits. OOP or Object Oriented Programming is a programming feature where copies of a class can be created. This chapter will go over static classes, properties, this
, and OOP.
7.1 - Static Classes
A class is a way of holding (or templating) subclasses, functions, properties, and traits. The idea that the class is static (keeps itself sealed) means that it will not be instantiated (having a new instance of the class declared).
Let's say you wanted to have a class that would contain four functions to do +
, -
, *
, and /
with three parameters. The class will be called Calculator
and will have those four functions inside of it.
func main () {
println (Calculator.add (5, 7, 8));
println (Calculator.mul (2, 5, 3));
}
class Calculator {
func add (x, y, z) {
return x + y + z;
}
func sub (x, y, z) {
return x - y - z;
}
func mul (x, y, z) {
return x * y * z;
}
func div (x, y, z) {
return x / y / z;
}
}
When the functions are declared inside of the Calculator
class, they become children of that class. This means that you could not just call add
from main
, as add
is a member (or child) of Calculator
. To access add
we use the .
attribute access operator. The left hand side is the parent we are accessing, Calculator
, while the right hand side is the attribute we wish to access, add
.
7.1.1 Static - this
Hassium has a unique reserved variable called this
. this
refers to the parent object of wherever it is accessed from. Inside of the sub
function in 7.1, this
refers to Calculator
. Inside of main
, it refers to the global scope.
When calling other child functions of the same class, it is best practice to be explicit and use a this
variable. Let's add to the Calculator class a function called special
, which will return the result of adding x
, y
, and z
divided by the result of subtracting x
, y
, and z
.
class Calculator {
func add (x, y, z) {
return x + y + z;
}
func sub (x, y, z) {
return x - y - z;
}
func mul (x, y, z) {
return x * y * z;
}
func div (x, y, z) {
return x / y / z;
}
func special (x, y, z) {
return this.add (x, y, z) / this.sub (x, y, z);
}
}
In the function Calulator.special
, when the identifier this
is encountered, the parent of special
is accessed, which is Calculator
.
7.1.2 Static - Properties
Properties are data members of a class which can be accessed and assigned to like a variable, although the programmer defines the specific behavior for the property.
Here is a class then has two properties, one that gets or sets the name, and one that gets the name in caps or sets.
func main () {
Person.name = "Jerry";
println (Person.name); # prints "Jerry"
println (Person.nameInCaps); # prints "JERRY"
Person.name = "Susan";
println (Person.nameInCaps); # prints ("SUSAN"
}
class Person {
name { get { return this.name_ } set { this.name_ = value; } }
nameInCaps { get { return this.name_.toUpper (); } set { this.name_ = value; } }
}
main
begins by assigning the value "Jerry"
to Person.name
, which takes this value
and assigns it to this.name_
. The second line of main
accesses or gets the value of Person.name
, which in turn returns the value of this.name_
. The third line of mine gets the value of Person.nameInCaps
, which returns the value of this.name_.toUpper ()
. The fourth and fifth lines of main
reassign Person.name
and print out the caps value of the reassignment.
7.1.3 Static - Subclasses
Classes can also hold an infinite amount of classes inside them, referred to a subclasses. Here is a simple program that declares a class containing two subclasses and one function inside them.
func main () {
ParentClass.SubClass1.SubClass2.subfunc ();
}
class ParentClass {
class SubClass1 {
class SubClass2 {
func subfunc () {
println ("Hello, World! From ParentClass.SubClass1.SubClass2.subfunc");
}
}
}
}
Output:
Hello, World! From ParentClass.SubClass1.SubClass2.subfunc
7.2 Object Oriented Programming
OOP (Object Oriented Programming) refers mainly to the instantiation (creation of a copy) of classes. Instead of having a static class where the state is fixed, programmers can treat the class like a template or blueprint, creating new instances of that class that have their own scopes.
Here is a simple program that shows what OOP can do.
func main () {
Person person1 = new Person ("Bruce");
Person person2 = new Person ("Michael");
println (person1.name); # prints Bruce
println (person2.name); # prints Michael
person1.name = "Caitlyn";
println (person1.name); # prints Caitlyn
println (person2.name); # prints Michael
}
class Person {
name { get { return this.name_; } set { this.name_ = value; } }
func new (name : string) {
this.name_ = name;
}
}
Output:
Bruce
Michael
Caitlyn
Michael
There is a lot of new things to take in here. The Person
class contains a function named new
. This is the class constructor (function called when class is instantiated). This constructor takes in the string
parameter name
and assigns it to this.name_
. The property Person.name
then gets or sets this.name_
. In main
, the first two lines make new instances of the Person
class by calling new Person
. The names of each Person
object are displayed on the fifth and sixth lines of main
by accessing each Person
's name
property. The eighth line of main
reassigns the person1
name
property to "Caitlyn"
. The final lines of main
then print out the new value of person1.name
and the same value of person2.name
.
7.2 OOP - Inheritance
Using inheritance (concept where classes can take on the members of other classes), a class can inherit the functions, properties, subclasses, and traits of another class.
Say we had a class called Person
. That might contain basic information like name, age, and DOB. What if we wanted to have a class for President
? This would still be a Person
, also having a name, age, and DOB. But the President
class might need to have other data, such as year elected and party.
Let's write and test the Person
class.
func main () {
println (new Person ("Michael", 43, "3/6/1973"));
}
class Person {
name { get { return this.name_; } set { this.name_ = value; } }
age { get { return this.age_; } set { this.age_ = value; } }
DOB { get { return this.dob_; } set { ; } }
func new (name : string, age : int, DOB : string) {
this.name_ = name;
this.age_ = age;
this.dob_ = DOB;
}
func tostring () : string {
return "Name: {0}, Age: {1}, DOB: {2}".format (this.name_, this.age_, this.dob_);
}
}
Output:
Name: Michael, Age: 43, DOB: 3/6/1973
An important side note is the tostring
function inside of the Person
class. When println
accepts an object argument, it calls tostring
on the object automatically.
Now it is time to implement the President
class. This class will need to have all the attributes of Person
and more. To accomplish this, the President
class will inherit the Person
class using the :
inherit operator.
func main () {
println (new Person ("Dave", 43, "3/6/1973"));
println (new President ("TheDonald", 70, "6/14/1946", "2016", "Republican"));
}
class President : Person {
yearelected { get { return this.yearelected_; } set { ; } }
party { get { return this.party_; } set { ; } }
func new (name : string, age : int, DOB : string, yearelected : int, party : string) {
this.name_ = name;
this.age_ = age;
this.dob_ = DOB;
this.yearelected_ = yearelected;
this.party_ = party;
}
func tostring () : string {
return "Name: {0}, Age: {1}, DOB: {2}, Year Elected: {3}, Party: {4}".format (this.name_, this.age_, this.dob_, this.yearelected_, this.party_);
}
}
Output:
Name: Dave, Age: 43, DOB: 3/6/1973
Name: TheDonald, Age: 70, DOB: 6/14/1946, Year Elected: 2016, Party: Republican
The class President
inherits all of the members of Person
and adds the properties yearelected
and party
. Because both the Person
class and the President
class both have the member function tostring
, one version of tostring
must be chosen. Since it is Person
that is being inherited, the version of tostring
in President
will be the one used.
Chapter 7 - Exercises
Exercise 7.1
Create a class called Dog
which has all the attributes of a dog. Include some methods like bark
and eat
.
Exercise 7.2
Create a class called BigDog
which inherits the attributes from Dog
but adds methods relevant to a larger dog.