In the real-world, different entities (people, animals, cars, you name it) are related in various ways. Within a single entity or group, there exist systems of classification. For example, the "dogs" entity or category includes pugs, corgis, labs, etc. All of these breeds share common features because they are all dogs. But they all have certain unique traits as well.
Another example: you are writing a web application in which users are either admins, instructors or students. All of these entities are "users" and have common features, but they all have some unique traits as well.
How can our code reflect that fact that these different categories of things all share some, or even many, characteristics but all have some unique attributes as well? Well, we could write separate admin, instructor and student class that each contain repetitious code to lend each of these classes shared attributes and behaviors. We know, however, that repetitious code is always something to be avoided. Not only is it time consuming, but what happens when we need to make a change to this shared behavior? We'd have to code the same change in three places.
Instead, we can use inheritance. The use of inheritance allows us to create a family of classes with shared behavior, while still differentiating those classes. With inheritance, we could inherit the admin, instructor and student classes from a user class. Then, any changes made to the user class would apply to the other class.
While you may not write your own classes that use inheritance very frequently, you will encounter it frequently as a Ruby on Rails web developer. Once we introduce the use of databases and the challenge of connecting our programs to our database, you'll encounter inheritance in nearly every program you write for the web. More on that (much) later.
In Ruby, classes can inherit from one another. This means that they adopt all of the attributes and behaviors (i.e. all of the methods) of the parent, also called the super class. In this exercise, we'll be building our own chain of inheritance.
In this domain model, we have class
Vehicle that will act as the parent, or super, class. We will create child classes, also known as subclasses for different types of
Vehicles, such as car.
lib/vehicle.rb. We're going to define some methods in this parent class so that our subclasses, when we make them, will have access to them.
class Vehicle attr_accessor :wheel_size, :wheel_number def initialize(wheel_size, wheel_number) @wheel_size = wheel_size @wheel_number = wheel_number end def go "vrrrrrrrooom!" end def fill_up_tank "filling up!" end end
Vehicle initialize with a wheel size and number. We also have
#fill_up_tank instance methods that describe some common vehicle behavior.
Go ahead and paste the above Vehicle class code into your Vehicle class, and run the test suite and you'll see that you are passing all of the tests for the
Vehicle class but none of the tests for the
lib/car.rb. Notice that we are requiring
lib/vehicle.rb. That is because our
Car class will need access to the
Vehicle class and will therefore need access to the file that contains that class.
Go ahead and define the class in the following way:
class Car < Vehicle end
We use the
< to inherit the
Car class from
Vehicle. Notice that there are no methods defined in the
Run the test suite again and you'll see that you are passing a number of tests for the
Wow! We didn't write anything in our
Car class but instances of
Car class inherit all of the
Vehicle methods and therefore have access to them. We're still failing the
#go test however. Looks like the test is expecting the
#go method on an individual car to return the phrase:
"VRRROOOOOOOOOOOOOOOOOOOOOOOM!!!!!". This is different than the return value of the
#go method that we inherited from the
Let's overwrite the inherited
go method with one specific to
lib/car.rb, write the following method:
class Car < Vehicle def go "VRRROOOOOOOOOOOOOOOOOOOOOOOM!!!!!" end end
Now, run the tests again and you should be passing all of them.
How does our above example work? Well, when your program is being executed, at the point at which the
#go method is invoked, the compiler will first look in the class to which the instance of car that we are calling the method on belongs. If it finds a
#go method there, it will execute that method. If it doesn't find such a method there, it will move on to look in the parent class that this class inherits from.
View Intro to Inheritance on Learn.co and start learning to code for free.