What does it mean when someone says a programming language has a type hierarchy?
I was reading somewhere on the topic whether Go is an OOP language or not; and an argument supporting that Go isn't, started with "Since Go doesn't have type hierarchy..."
Go is a strange breed, it doesn't have many of the properties of OOP, in fact, it recommends against ideas like encapsulation and hierarchy. It comes from the idea of keeping it simple.
Type hierarchy has do with inheritance, and how when you say that an object inherits from another object, you are saying that object is another object.
A cellphone is a phone, a car is a vehicle, a cat is an animal. Biologists love this so much, they created a hierarchy of every living thing. But in Go, things are different.
So in Go, in order to inherit a struct, you may write this:
type Person struct {
Name string
DateOfBirth time.Time
}
type Employee struct {
Person
Position string
Supervisor *Person
}
In other languages, the employee object would then obtain the properties of person, but in Go, it embeds the Person struct in Employee. To demonstrate this, let's create an object.
So far, it seems like we inherited the properties and everything lies on our object. So let's just print it out to show off to everyone that we can inherit in Go:
Now we can see our object, but something looks strange. Why is there a set of curly brackets within a set of curly brackets? In fact, those curly brackets are strangely around the properties of Person.
This is what it means to embed the object. You see, when you "inherit" in Go, what is actually happening, Go is creates the base object, stuffs it into the inherited object, and pretends that it has all the properties of the base. In fact, you can still access the Person object in the struct.
Changes you make to that person object will be reflected in the inherited object. You can even swap out that person object with another. It is essentially treated as another property, you just gain a few shortcuts to its properties.
This is how Go differentiates itself from other languages. It doesn't actually give you the ability to say that an object is another object. If you were to try this:
var person Person = empl
You would get a type assignment error, saying that Employee and Person do not match. It doesn't even work if you used a pointer to reference it as a Person. To Go, an Employee is not a Person. So how is this even useful?
Well remember that we were able to still access the Person object. Well, by creating a pointer to that object, you can pass around the Person properties of that employee:
But that isn't all. You also inherit the methods of an object as well. So if a person can dance, so can an employee. This has the effect of if a person implements a interface, an employee does so as well, so you will not have to reference the Person object when you are passing to an interface, an employee will work just as fine.
Now, concepts like abstract classes do not work in Go. Structs are concrete things that can always be touched and created. If you want something like an abstract class, you will have to go with interfaces. Interfaces are more flexible in Go, considering their duck typing abilities, but that will have to be another topic.
The important thing to remember is that an Employee is not a Person.
Daniel J Dominguez
Go is a strange breed, it doesn't have many of the properties of OOP, in fact, it recommends against ideas like encapsulation and hierarchy. It comes from the idea of keeping it simple.
Type hierarchy has do with inheritance, and how when you say that an object inherits from another object, you are saying that object is another object.
A cellphone is a phone, a car is a vehicle, a cat is an animal. Biologists love this so much, they created a hierarchy of every living thing. But in Go, things are different.
So in Go, in order to inherit a struct, you may write this:
type Person struct { Name string DateOfBirth time.Time } type Employee struct { Person Position string Supervisor *Person }In other languages, the employee object would then obtain the properties of person, but in Go, it embeds the Person struct in Employee. To demonstrate this, let's create an object.
var empl Employee empl.Name = "Daniel J Dominguez" empl.DateOfBirth = time.Date(1992, 10, 14, 0, 0, 0, 0, time.UTC) empl.Position = "Developer"So far, it seems like we inherited the properties and everything lies on our object. So let's just print it out to show off to everyone that we can inherit in Go:
fmt.Println(empl){{Daniel J Dominguez 1992-10-14 00:00:00 +0000 UTC} Developer <nil>}Now we can see our object, but something looks strange. Why is there a set of curly brackets within a set of curly brackets? In fact, those curly brackets are strangely around the properties of Person.
This is what it means to embed the object. You see, when you "inherit" in Go, what is actually happening, Go is creates the base object, stuffs it into the inherited object, and pretends that it has all the properties of the base. In fact, you can still access the Person object in the struct.
fmt.Println(empl.Person)Changes you make to that person object will be reflected in the inherited object. You can even swap out that person object with another. It is essentially treated as another property, you just gain a few shortcuts to its properties.
This is how Go differentiates itself from other languages. It doesn't actually give you the ability to say that an object is another object. If you were to try this:
var person Person = emplYou would get a type assignment error, saying that Employee and Person do not match. It doesn't even work if you used a pointer to reference it as a Person. To Go, an Employee is not a Person. So how is this even useful?
Well remember that we were able to still access the Person object. Well, by creating a pointer to that object, you can pass around the Person properties of that employee:
legal.CanDrink(empl.Person) legal.ChangeName(&empl.Person, "No one")But that isn't all. You also inherit the methods of an object as well. So if a person can dance, so can an employee. This has the effect of if a person implements a interface, an employee does so as well, so you will not have to reference the Person object when you are passing to an interface, an employee will work just as fine.
Now, concepts like abstract classes do not work in Go. Structs are concrete things that can always be touched and created. If you want something like an abstract class, you will have to go with interfaces. Interfaces are more flexible in Go, considering their duck typing abilities, but that will have to be another topic.
The important thing to remember is that an Employee is not a Person.