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! 🎭


Upp

Upp


Licens: Apache 2.0 | © 2023 Marcus Medina, Campus Mölndal. Alla rättigheter förbehållna.
Du får använda och modifiera detta verk enligt villkoren i Apache License, Version 2.0. Du får inte använda detta verk för kommersiella ändamål utan tillstånd från upphovsmannen.