Sdílet prostřednictvím


abstract (Referenční dokumentace jazyka C#)

abstract Modifikátor označuje, že změněná věc má chybějící nebo neúplnou implementaci. Abstraktní modifikátor lze použít s třídami, metodami, vlastnostmi, indexery a událostmi. abstract Modifikátor v deklaraci třídy slouží k označení, že třída je určena pouze jako základní třída jiných tříd, nikoli vytvoření instance sama. Členy označené jako abstraktní musí být implementovány ne abstraktní třídy, které jsou odvozeny z abstraktní třídy.

Abstraktní třídy mohou obsahovat abstraktní členy (které nemají žádnou implementaci a musí být přepsány v odvozených třídách) a plně implementované členy (například běžné metody, vlastnosti a konstruktory). To umožňuje abstraktní třídy poskytovat společné funkce, zatímco stále vyžadují odvozené třídy k implementaci konkrétních abstraktních členů.

Příklad 1 – abstraktní třída se smíšenými členy

Následující příklad ukazuje abstraktní třídu, která obsahuje implementované metody i abstraktní členy:

namespace LanguageKeywords;

public abstract class Vehicle
{
    protected string _brand;
    
    // Constructor - implemented method in abstract class
    public Vehicle(string brand) => _brand = brand;
    
    // Implemented method - provides functionality that all vehicles share
    public string GetInfo() => $"This is a {_brand} vehicle.";
    
    // Another implemented method
    public virtual void StartEngine() => Console.WriteLine($"{_brand} engine is starting...");
    
    // Abstract method - must be implemented by derived classes
    public abstract void Move();
    
    // Abstract property - must be implemented by derived classes  
    public abstract int MaxSpeed { get; }
}

public class Car : Vehicle
{
    public Car(string brand) : base(brand) { }
    
    // Implementation of abstract method
    public override void Move() => Console.WriteLine($"{_brand} car is driving on the road.");
    
    // Implementation of abstract property
    public override int MaxSpeed => 200;
}

public class Boat : Vehicle
{
    public Boat(string brand) : base(brand) { }
    
    // Implementation of abstract method
    public override void Move() => Console.WriteLine($"{_brand} boat is sailing on the water.");
    
    // Implementation of abstract property
    public override int MaxSpeed => 50;
}

public class AbstractExample
{
    public static void Examples()
    {
        // Cannot instantiate abstract class: Vehicle v = new Vehicle("Generic"); // Error!
        
        Car car = new Car("Toyota");
        Boat boat = new Boat("Yamaha");
        
        // Using implemented methods from abstract class
        Console.WriteLine(car.GetInfo());
        car.StartEngine();
        
        // Using abstract methods implemented in derived class
        car.Move();
        Console.WriteLine($"Max speed: {car.MaxSpeed} km/h");
        
        Console.WriteLine();
        
        Console.WriteLine(boat.GetInfo());
        boat.StartEngine();
        boat.Move();
        Console.WriteLine($"Max speed: {boat.MaxSpeed} km/h");
    }
}

class Program
{
    static void Main()
    {
        AbstractExample.Examples();
    }
}
/* Output:
This is a Toyota vehicle.
Toyota engine is starting...
Toyota car is driving on the road.
Max speed: 200 km/h

This is a Yamaha vehicle.
Yamaha engine is starting...
Yamaha boat is sailing on the water.
Max speed: 50 km/h
*/

V tomto příkladu Vehicle poskytuje abstraktní třída:

  • Implementované členy: GetInfo() metoda, StartEngine() metoda a konstruktor – poskytují společné funkce pro všechna vozidla.
  • Abstraktní členy: Move() metoda a MaxSpeed vlastnost – musí být implementovány jednotlivými konkrétními typy vozidel.

Tento návrh umožňuje abstraktní třídě poskytovat sdílené funkce a zároveň zajistit, aby odvozené třídy implementovaly chování specifické pro vozidla.

Příklad 2

V tomto příkladu musí třída Square poskytnout implementaci GetArea , protože je odvozena z Shape:

abstract class Shape
{
    public abstract int GetArea();
}

class Square : Shape
{
    private int _side;

    public Square(int n) => _side = n;

    // GetArea method is required to avoid a compile-time error.
    public override int GetArea() => _side * _side;

    static void Main()
    {
        var sq = new Square(12);
        Console.WriteLine($"Area of the square = {sq.GetArea()}");
    }
}
// Output: Area of the square = 144

Abstraktní třídy mají následující funkce:

  • Abstraktní třídu nelze vytvořit instanci.

  • Abstraktní třída může obsahovat abstraktní metody a přístupové objekty.

  • Abstraktní třída může také obsahovat implementované metody, vlastnosti, pole a další členy, které poskytují funkce odvozeným třídám.

  • Abstraktní třídu s zapečetěným modifikátorem není možné upravit, protože tyto dva modifikátory mají opačný význam. sealed Modifikátor zabraňuje dědění třídy a abstract modifikátor vyžaduje, aby byla zděděna třída.

  • Abstraktní třída odvozená z abstraktní třídy musí obsahovat skutečné implementace všech zděděných abstraktních metod a přístupových objektů.

abstract Použijte modifikátor v metodě nebo deklaraci vlastnosti k označení, že metoda nebo vlastnost neobsahuje implementaci.

Abstraktní metody mají následující funkce:

  • Abstraktní metoda je implicitně virtuální metoda.

  • Deklarace abstraktní metody jsou povoleny pouze v abstraktních třídách.

  • Vzhledem k tomu, že deklarace abstraktní metody neposkytuje žádnou skutečnou implementaci, neexistuje žádný tělo metody; deklarace metody jednoduše končí středníkem a za podpisem nejsou žádné složené závorky ({ }). Příklad:

    public abstract void MyMethod();  
    

    Implementace je poskytována přepsáním metody, která je členem ne abstraktní třídy.

  • Jedná se o chybu použití statických nebo virtuálních modifikátorů v abstraktní deklaraci metody.

Abstraktní vlastnosti se chovají jako abstraktní metody, s výjimkou rozdílů v deklaraci a syntaxi vyvolání.

  • Jedná se o chybu použití modifikátoru abstract u statické vlastnosti.

  • Abstraktní zděděná vlastnost lze přepsat v odvozené třídě zahrnutím deklarace vlastnosti, která používá modifikátor přepsání .

Další informace o abstraktních třídách naleznete v tématu Abstraktní a zapečetěné třídy a členy třídy.

Abstraktní třída musí poskytovat implementaci pro všechny členy rozhraní.

Abstraktní třída, která implementuje rozhraní, může mapovat metody rozhraní na abstraktní metody. Příklad:

interface I
{
    void M();
}

abstract class C : I
{
    public abstract void M();
}

Příklad 3

V tomto příkladu je třída DerivedClass odvozena z abstraktní třídy BaseClass. Abstraktní třída obsahuje abstraktní metodu , AbstractMethoda dvě abstraktní vlastnosti, X a Y.

// Abstract class
abstract class BaseClass
{
    protected int _x = 100;
    protected int _y = 150;

    // Abstract method
    public abstract void AbstractMethod();

    // Abstract properties
    public abstract int X { get; }
    public abstract int Y { get; }
}

class DerivedClass : BaseClass
{
    public override void AbstractMethod()
    {
        _x++;
        _y++;
    }

    public override int X   // overriding property
    {
        get
        {
            return _x + 10;
        }
    }

    public override int Y   // overriding property
    {
        get
        {
            return _y + 10;
        }
    }

    static void Main()
    {
        var o = new DerivedClass();
        o.AbstractMethod();
        Console.WriteLine($"x = {o.X}, y = {o.Y}");
    }
}
// Output: x = 111, y = 161

Pokud se v předchozím příkladu pokusíte vytvořit instanci abstraktní třídy pomocí příkazu, který je podobný tomuto:

BaseClass bc = new BaseClass();   // Error  

Zobrazí se chyba s informací, že kompilátor nemůže vytvořit instanci abstraktní třídy BaseClass.

Nicméně je možné použít abstraktní konstruktor třídy, jak je uvedeno v následujícím příkladu.

Příklad 4

public abstract class Shape
{
    public string Color { get; set; }

    // Constructor of the abstract class
    protected Shape(string color)
    {
        Color = color;
        Console.WriteLine($"Created a shape with color {color}.");
    }

    // Abstract method that must be implemented by derived classes
    public abstract double CalculateArea();
}

public class Square : Shape
{
    public double Side { get; set; }

    // Constructor of the derived class calling the base class constructor
    public Square(string color, double side) : base(color)
    {
        Side = side;
    }

    public override double CalculateArea()
    {
        return Side * Side;
    }
}

public class Program
{
    public static void Main(string[] args)
     {
            Square square = new Square("red", 5);
            Console.WriteLine($"Area of the square: {square.CalculateArea()}");            
     }
}

Třída Shape je deklarována abstract, což znamená, že nelze instancovat přímo. Místo toho slouží jako podrobný plán pro jiné třídy.

  • I když nemůžete vytvářet objekty abstraktní třídy, může mít stále konstruktor. Tento konstruktor je obvykle protected, což znamená, že k němu lze přistupovat pouze z odvozených tříd. V tomto případě konstruktor Shape přebírá color parametr a inicializuje Color vlastnost. Vytiskne také zprávu do konzoly. Část public Square(string color, double side) : base(color) volá konstruktor základní třídy (Shape) a předává mu argument color.
  • Ve třídě Shape definovaný konstruktor přebírá barvu jako parametr protected Shape(string color). To znamená, že už neexistuje výchozí konstruktor bez parametrů automaticky poskytovaný jazykem C#, takže odvozené třídy musí k vyvolání základního konstruktoru použít výraz : base(color). Nastavení výchozí hodnoty na barvu protected Shape(string color="green") umožní vynechat výraz : base(color) v odvozených třídách, stále takový konstruktor protected Shape(string color="green") bude vyvolán a nastaví barvu na zelenou.

Specifikace jazyka C#

Další informace najdete v tématu Specifikace jazyka C#. Specifikace jazyka je úplným a rozhodujícím zdrojem pro syntaxi a použití jazyka C#.

Viz také