It was incredibly annoying to wait for Noname to scan the files on the hidden server. Bored with waiting, I began trawling a local Wonderland network to see if I could learn anything new.
The first five to ten pages that I looked at was just mindless drivel. A few articles about resource gathering in Wonderland, a political one describing the importance of resistance, a pity story about a family where she was a resistance fighter and he decided to work for the machines. (In the end, she accidentally shot him.) Getting discouraged, I started clicking through faster and faster.
Click, click, click, wait - go back! On one of the pages, a bold headline that said "Learn About Mind-Reading Chips" attracted my attention. Without hesitation, I followed it.
The article began by describing newly discovered chips that the resistance managed to steal from machines and which they hoped to one day reproduce. The chips were first found embedded into former human prisoners' heads and acted to connect humans to humans and humans to ... machines. The first type of connection was described in all possible aspects: for instance, a mother could connect with her child to know in-depth how he or she felt. In other scenarios, couples connected via one of these chips were discovering something new in their relationships; they called it "integrated emotional binding." The second type of connection, between humans and machines, was scarcely explained at all. It seemed a bit shady that this article would omit the part where enemies were forced to be mentally in sync with one another. Why omit the part that we were all fighting to prevent? Aren't there enough secrets in this place already?
I wondered if there was a history available for this page. Fortunately, there was a log of all changes to this article for the last 5 years. There was quite a bit of material, but the most significant change appeared to have happened the day before I first arrived at Wonderland. It was titled "Final cleanup." I opened it, eager to catch every word.
Of course, I should have known that getting any useful information wouldn't be that easy. There was protection on the change log. It required knowing something, called " inheritance ." The only thing left to do was to search for that term in the system and learn enough to get access to the change log. The timing of the massive change couldn't be a coincidence, and I had a gut feeling something important was hiding in there.
Inheritance is a mechanism of basing an object or class upon another object or class, retaining similar implementation. Inheritance allows you to re-use functionality that is already implemented in another class, and also to add custom logic on top of it. For example, let's say you have a class Pet .
class Pet
{
public string Name { get; set; }
public void PrintName()
{
Console.WriteLine($"My name is {Name}");
}
}
This class really is as simple as it looks. It prints a pet's name to the console when you call the PrintName method. Now, let's imagine that your customer made a new request - to create a class specifically for a pet cat. It should have the same method, PrintName, as well as an additional one, PrintBreed, which prints the cat's breed. To solve this, you could create such a class as follows:
class Cat
{
public string Name { get; set; }
public string Breed { get; set; }
public void PrintName()
{
Console.WriteLine($"My name is {Name}");
}
public void PrintBreed()
{
Console.WriteLine($"My breed is {Breed}");
}
}
If you look closer, you can see that the class Cat just duplicated the functionality of the class Pet . The code for the property Name and method PrintName are copied from the class Pet. This approach has a couple key disadvantages:
To avoid duplication in the class Cat , we can use inheritance . The following is an example of what the code looks like if the class is derived from another one:
class Pet
{
public string Name { get; set; }
public void PrintName()
{
Console.WriteLine($"My name is {Name}");
}
}
class Cat : Pet // Class Cat derives from the class Pet
{
public string Breed { get; set; }
public void PrintBreed()
{
Console.WriteLine($"My breed is {Breed}");
}
}
public class ClassWithMain
{
public static void Main()
{
Cat mrMartin = new Cat
{
Name = "mr Martin", // Property Name is derived from the class Pet
Breed = "Siamese"
};
mrMartin.PrintName(); // PrintName is derived from the class Pet
mrMartin.PrintBreed();
}
}
// Outputs:
// My name is mrMartin
// My breed is Siamese
When you re-use the functionality of one class in another one by using inheritance, you are deriving one class from another. The class whose members are inherited is called the base class , and the class that inherits those members is called the derived class . A derived class can have only one direct base class. In our example, class Pet is the base class and the class Cat is a derived one. To derive class A from class B, use a colon (:) after the class A name, and then append the name for class B. You can treat it as a copy of the code from the class B to class A.
In the example above, we derived class Cat from class Pet . Having done that, we can now use the property Name and the method PrintName on every object of type Cat .
As you can see, there is no code duplication when you use inheritance . It all happens behind the scenes.
Conceptually, the connection between classes that are represented by
inheritance can be thought of as an
"
is
" relationship. A derived class
is
a specialization of the base class. In our example: a cat
is
a pet; that's why
Cat
derives from
Pet
. Beginners often wonder when one class should or should not derive from
another one. A good check would be to apply the "is" rule. If one of them
"is" another, you can apply inheritance, otherwise - don't. Here are some
more examples:
When writing code, always check whether inheritance makes sense in the current context with the is rule.
Inheritance is transitive. This means if B is derived from C , and A is derived from B , then A is also derived from C :
class C
{
public void PrintCName()
{
Console.WriteLine("I'm class C");
}
}
class B : C
{
public void PrintBName()
{
Console.WriteLine("I'm class B");
}
}
class A : B
{
public void PrintAName()
{
Console.WriteLine("I'm class A");
}
}
public class ClassWithMain
{
public static void Main()
{
var a = new A();
a.PrintAName();
a.PrintBName(); // Inherited from class B
a.PrintCName(); // Inherited from class C
}
}
// Outputs:
// I'm class A
// I'm class B
// I'm class C
As you can see, class A derives from B and B derives from C . Therefore, B gets all functionality from C and A gets all functionality from both B and C .
Note that it is NOT possible to derive a class from more than one class .
class C
{
public void PrintCName()
{
Console.WriteLine("I'm class C");
}
}
class B
{
public void PrintBName()
{
Console.WriteLine("I'm class B");
}
}
class A : B, C // ERROR!!! Can't derive from more than one class
{
public void PrintAName()
{
Console.WriteLine("I'm class A");
}
}
Noname was taking so long that I fell asleep while trying to commit all the vageries of inheritance to memory. If you have any trouble sleeping, I can heartily confirm that reading about inheritance in OOP for twenty minutes will do the trick. You are welcome!