Arv
Inheritance är som familje-DNA - du ärver saker från dina föräldrar, men du är ändå din egen person! I kod betyder det att barnklasser ärver superkrafter från föräldrarna, men kan utveckla sina egna unika talanger! 👨👩👧👦
🎯 Efter denna artikel kommer du att:
- Förstå inheritance konceptet - parent-child relationships i kod 👪
- Skapa arvshierarkier - base classes och derived classes 📊
- Använda virtual/override - polymorfism på svenska! 🎭
- Hantera sealed classes - när arvet slutar! 🔒
🏗️ Basic Inheritance - Byggstenar för Kodåtervinning
Base Class (Parent) - Gemensamma Superkrafter
// Base class - alla fordon har dessa
public class Vehicle
{
// Protected - bara family får accessa
protected string _owner;
// Public properties
public string Make { get; set; }
public string Model { get; set; }
public int Year { get; set; }
public bool IsRunning { get; private set; }
// Constructor
public Vehicle(string make, string model, int year)
{
Make = make;
Model = model;
Year = year;
IsRunning = false;
}
// Virtual method - barn kan override detta
public virtual void StartEngine()
{
IsRunning = true;
Console.WriteLine($"🚗 {Make} {Model} engine started!");
}
public virtual void StopEngine()
{
IsRunning = false;
Console.WriteLine($"🚗 {Make} {Model} engine stopped.");
}
// Regular method - alla ärver samma
public void Honk()
{
Console.WriteLine("📯 BEEP BEEP!");
}
}
Derived Class (Child) - Specialiserade Talanger
// Car extends Vehicle - ärver ALLT + lägger till bil-specifikt
public class Car : Vehicle // : means "inherits from"
{
// New properties specific to cars
public int NumberOfDoors { get; set; }
public string FuelType { get; set; }
// Constructor - måste kalla parent constructor
public Car(string make, string model, int year, int doors, string fuel)
: base(make, model, year) // Kalla Vehicle constructor först
{
NumberOfDoors = doors;
FuelType = fuel;
}
// Override parent method - egen implementation
public override void StartEngine()
{
Console.WriteLine($"🔑 Inserting key for {Make} {Model}...");
base.StartEngine(); // Kalla parent version först
Console.WriteLine($"⛽ Running on {FuelType}");
}
// New method - bara Car har denna
public void OpenTrunk()
{
Console.WriteLine($"📦 {Make} {Model} trunk opened!");
}
}
Grandchild Class - Tredje Generationen
// SportsCar extends Car - multilevel inheritance!
public class SportsCar : Car
{
public int TopSpeed { get; set; }
public bool HasTurbo { get; set; }
public SportsCar(string make, string model, int year, int topSpeed)
: base(make, model, year, 2, "Gasoline") // Sports cars = 2 doors, gas
{
TopSpeed = topSpeed;
HasTurbo = true;
}
// Override CAR's version (som redan overrode VEHICLE's version)
public override void StartEngine()
{
Console.WriteLine($"🏎️ SPORTS CAR STARTUP SEQUENCE for {Make} {Model}");
if (HasTurbo)
Console.WriteLine("💨 Turbo system activated!");
base.StartEngine(); // Kalla Car's version
Console.WriteLine($"🚀 Ready to reach {TopSpeed} km/h!");
}
// Unique sports car method
public void ActivateSpeedMode()
{
Console.WriteLine($"🏁 {Make} {Model} entering SPEED MODE!");
Console.WriteLine($"💯 Max speed: {TopSpeed} km/h unlocked!");
}
}
🔑 Access Modifiers - Vem får se familjesekterna?
public class BankAccount // Parent class
{
public string AccountNumber { get; set; } // Alla kan se
protected decimal balance; // Bara family
private string _pin; // Bara denna class
public BankAccount(string accountNumber, string pin)
{
AccountNumber = accountNumber;
_pin = pin;
balance = 0; // Protected - children kan access detta
}
protected bool ValidatePin(string inputPin) // Family method
{
return _pin == inputPin;
}
public virtual void ShowBalance() // Public virtual
{
Console.WriteLine($"Balance: ${balance}");
}
}
public class PremiumAccount : BankAccount // Child class
{
private decimal _creditLimit;
public PremiumAccount(string accountNumber, string pin, decimal creditLimit)
: base(accountNumber, pin)
{
_creditLimit = creditLimit;
}
public void SpecialDeposit(string pin, decimal amount)
{
// Can access PROTECTED members from parent
if (ValidatePin(pin)) // ✅ Protected method - OK!
{
balance += amount; // ✅ Protected field - OK!
Console.WriteLine($"✅ Deposited ${amount}");
}
else
{
Console.WriteLine("❌ Invalid PIN!");
}
// Can't access private members
// Console.WriteLine(_pin); // ❌ Compilation error!
}
public override void ShowBalance() // Override virtual method
{
Console.WriteLine($"💎 Premium Balance: ${balance}");
Console.WriteLine($"💳 Available Credit: ${_creditLimit - balance}");
}
}
⚠️ Inheritance Gotchas och Best Practices
💥 Common Mistakes
Mistake #1: Constructor Chain Confusion
public class Vehicle
{
public string Make { get; set; }
// Ingen parameterless constructor!
public Vehicle(string make)
{
Make = make;
}
}
public class Car : Vehicle
{
// ❌ Detta kompilerar inte:
// public Car() { } // Ingen matching base constructor!
// ✅ Måste kalla base constructor:
public Car(string make) : base(make)
{
// OK now!
}
}
Mistake #2: Virtual in Constructor (Dangerous!)
public class Parent
{
public Parent()
{
DoSomething(); // ❌ Calls virtual method in constructor - dangerous!
}
public virtual void DoSomething()
{
Console.WriteLine("Parent version");
}
}
public class Child : Parent
{
private string data = "Important data";
public override void DoSomething()
{
Console.WriteLine(data.ToUpper()); // CRASH! data is null during base construction
}
}
// new Child(); // Runtime exception!
Mistake #3: Deep Inheritance Hierarchies
// ❌ TOO DEEP - maintenance nightmare:
public class A { }
public class B : A { }
public class C : B { }
public class D : C { }
public class E : D { }
public class F : E { } // 6 levels deep - too much!
// ✅ PREFER COMPOSITION over deep inheritance
public class ComplexObject
{
private ComponentA compA;
private ComponentB compB;
// Combine instead of inherit
}
🆚 Inheritance vs Composition - När använda vad?
🌳 Använd INHERITANCE när:
- “Is-a” relationship: Dog IS-A Animal
- Shared behavior är core till conceptet
- Du vill polymorphism (treat different types uniformly)
// ✅ Good inheritance - clear "is-a" relationship
public class Vehicle { }
public class Car : Vehicle { } // Car IS-A Vehicle
public class Truck : Vehicle { } // Truck IS-A Vehicle
🧩 Använd COMPOSITION när:
- “Has-a” relationship: Car HAS-A Engine
- Du vill flexibilitet
- Du vill testability
// ✅ Good composition - "has-a" relationship
public class Car
{
private Engine engine; // Car HAS-A Engine
private Wheels wheels; // Car HAS-A Wheels
private Radio radio; // Car HAS-A Radio
public Car(Engine engine, Wheels wheels)
{
this.engine = engine;
this.wheels = wheels;
}
}
💡 Marcus Inheritance Wisdom
“Inheritance är som att bygga en familjedynasti - kraftfullt när det görs rätt, men kan bli riktigt komplicerat om man inte tänker efter! Som en familj: håll det enkelt och var snäll mot varandra!” 👨👩👧👦
Real story: Första gången jag såg 8-level deep inheritance (2004) tänkte jag “wow så smart!” Tre månader senare när jag skulle bugfixa… 😱 Nu använder jag max 3-4 nivåer och composition wherever possible!
Pro tip: Inheritance är ett verktyg, inte ett mål. Fråga dig: “Är detta verkligen en is-a relationship?” Om svaret är nej, use composition instead! 🧩
Ready för Polymorphism och Interfaces? Inheritance är grunden - nu blir det riktigt magical! 🎭