C# 中的继承、多态和接口

继承、多态性和接口是面向对象编程 (OOP) 中的基础概念,可用于创建可扩展、模块化和可重用的代码。理解并有效运用这些原则对于构建强大的软件系统至关重要。本指南将深入探讨这些概念,并提供实际示例和特别有用的场景。

1. 为什么这些概念很重要?

可扩展性和模块化

  • 继承允许新类建立在现有类之上,从而实现代码重用。
  • 多态性允许方法根据对象类型表现出不同的行为,从而简化了可扩展性。
  • 接口定义了确保一致性同时允许实施灵活性的契约。
  • 何时选择继承还是接口

  • 当您想要建立“是一种”关系时,请使用继承(例如,狗“是一种”动物)。
  • 当您想要定义多个不相关的类可以共享的功能或行为时,请使用接口(例如,一只鸟和一架飞机都可以实现IFlyable)。
  • 2. 继承

    继承允许一个类(子类)从另一个类(超类)继承属性和方法,促进代码重用和层次结构创建。

    继承的实例

    public class Animal
    {
        public string Name { get; set; }
    
        public void Eat()
        {
            Console.WriteLine($"{Name} is eating.");
        }
    }
    
    public class Dog : Animal
    {
        public void Bark()
        {
            Console.WriteLine($"{Name} is barking.");
        }
    }
    
    // Using inheritance
    Dog myDog = new Dog();
    myDog.Name = "Buddy";
    myDog.Eat();
    myDog.Bark();

    3.多态性

    多态性允许方法根据对象类型具有不同的行为。这可以通过方法覆盖或接口来实现。

    方法重写的多态性示例

    public class Bird
    {
        public virtual void Fly()
        {
            Console.WriteLine("The bird is flying.");
        }
    }
    
    public class Eagle : Bird
    {
        public override void Fly()
        {
            Console.WriteLine("The eagle soars at great heights.");
        }
    }
    
    // Using polymorphism
    Bird myBird = new Eagle();
    myBird.Fly(); // Output: The eagle soars at great heights.

    4. 接口

    接口定义了类必须遵守的契约,确保一致性,同时允许实现的灵活性。

    接口实现示例

    public interface IFlyable
    {
        void Fly();
    }
    
    public class Airplane : IFlyable
    {
        public void Fly()
        {
            Console.WriteLine("The airplane is flying.");
        }
    }
    
    public class Bird : IFlyable
    {
        public void Fly()
        {
            Console.WriteLine("The bird is flying.");
        }
    }
    
    // Using interfaces
    IFlyable airplane = new Airplane();
    IFlyable bird = new Bird();
    
    airplane.Fly();
    bird.Fly();

    使用接口处理错误

    添加验证可以使实现更加健壮:

    public class BankAccount
    {
        private decimal balance;
    
        public void Deposit(decimal amount)
        {
            if (amount <= 0)
            {
                Console.WriteLine("Deposit amount must be greater than zero.");
                return;
            }
            balance += amount;
            Console.WriteLine($"Deposit successful. New balance: {balance}");
        }
    }

    5. 组合示例:继承、多态和接口

    让我们创建一个结合这三个概念的实际示例:

    public interface IDriveable
    {
        void Drive();
    }
    
    public class Vehicle
    {
        public string Make { get; set; }
        public string Model { get; set; }
    
        public virtual void DisplayInfo()
        {
            Console.WriteLine($"Vehicle: {Make} {Model}");
        }
    }
    
    public class Car : Vehicle, IDriveable
    {
        public override void DisplayInfo()
        {
            Console.WriteLine($"Car: {Make} {Model}");
        }
    
        public void Drive()
        {
            Console.WriteLine("The car is driving.");
        }
    }
    
    public class Motorcycle : Vehicle, IDriveable
    {
        public override void DisplayInfo()
        {
            Console.WriteLine($"Motorcycle: {Make} {Model}");
        }
    
        public void Drive()
        {
            Console.WriteLine("The motorcycle is driving.");
        }
    }
    
    // Using the combined example
    IDriveable car = new Car { Make = "Toyota", Model = "Corolla" };
    IDriveable motorcycle = new Motorcycle { Make = "Harley-Davidson", Model = "Sportster" };
    
    car.Drive();
    motorcycle.Drive();

    6. 高级概念和模式

    与这些概念相关的模式

  • 策略模式:使用接口在算法之间动态切换。
  • 模板方法模式:使用继承来定义一个公共结构,并通过子类实现特定的行为。
  • 策略模式示例

    public interface IShippingStrategy
    {
        decimal CalculateShipping(decimal weight);
    }
    
    public class StandardShipping : IShippingStrategy
    {
        public decimal CalculateShipping(decimal weight) => weight * 1.5m;
    }
    
    public class ExpressShipping : IShippingStrategy
    {
        public decimal CalculateShipping(decimal weight) => weight * 3.0m;
    }
    }
    
    // Usage
    IShippingStrategy strategy = new ExpressShipping();
    Console.WriteLine($"Shipping cost: {strategy.CalculateShipping(10)}");