【C#知识点详解】基类、抽象类、接口类型变量与子类实例的归纳总结

今天来梳理一下基类、抽象类、接口不同类型变量和子类实例对象之间的关系。话不多说直接开始。

基本功能

  • 基类是具备完整功能的普通类,可直接创建实例。当基类有可复用的功能时,子类可直接继承,其主要作用是复用已有的变量、属性、方法。
  • 抽象类是不完整的模版类,不可以被直接创建实例。抽象类内部存在未被实现的抽象方法,子类继承抽象类后,需强制子类实现抽象方法。与普通类一样,抽象类同样存在可复用的变量、属性、方法。其主要作用是通过抽象方法约束子类结构,并同时拥有复用通用功能的能力。
  • 接口是纯方法定义,无任何功能的具体实现(C# 8.0 + 可加默认实现,但不推荐)。接口无法被实例化,需要继承后实现约定的方法。其主要作用是约定方法,并可以解除类的依赖关系,接口可以实现多重继承。

使用场景

基类、抽象类、接口都可以由子类继承,三者都可以由各自类型的引用变量持有子类实例。示例如下:

cs 复制代码
public class Program
{
    static void Main(string[] args)
    {
        BaseClass baseClass = new DerivedClass();
        AbstractClass abstractClass = new AbstractDerivedClass();
        Interface @interface = new InterfaceDerivedClass();

        Console.ReadKey();
    }
}

接下来就详细说明一下各自的区别和使用场景。

基类

基类是完整的普通了,封装了独立的变量、属性、方法。当子类继承基类时,可直接拥有基类的这些功能。示例如下:

cs 复制代码
public class Program
{
    static void Main(string[] args)
    {
        Animal dog = new Dog();
        dog.Call(); //输出:动物叫

        Animal cat = new Cat();
        cat.Call(); //输出:动物叫

        Console.ReadKey();
    }
}

public class Animal
{
    public void Call()
    {
        Console.WriteLine("动物叫");
    }
}

public class Dog : Animal
{
}

public class Cat : Animal
{
}

当基类方法标记为virtual时,子类可重写基类方法。虽然变量类型为基类(Animal),但创建出来的实例为子类(Dog、Cat),因此在方法的实际调用时,调用的是子类中重写的方法。示例代码如下:

cs 复制代码
public class Program
{
    static void Main(string[] args)
    {
        Animal dog = new Dog();
        dog.Call(); //输出:汪汪汪

        Animal cat = new Cat();
        cat.Call(); //输出:喵喵喵

        Console.ReadKey();
    }
}

public class Animal
{
    public virtual void Call()
    {
        Console.WriteLine("动物叫");
    }
}

public class Dog : Animal
{
    public override void Call()
    {
        Console.WriteLine("汪汪汪");
    }
}

public class Cat : Animal
{
    public override void Call()
    {
        Console.WriteLine("喵喵喵");
    }
}

通过上面的示例可以看出,可以通过基类类型统一的持有不同的子类类型,并调用子类中重写的方法,子类重写并非强制

通过这种特性,我们可以通过基类类型统一的管理不同的子类实例。如数组、方法参数等。示例如下:

cs 复制代码
public class Program
{
    static void Main(string[] args)
    {
        Animal[] animals = { new Dog(), new Cat() };
        for (int i=0;i<animals.Length;i++)
        {
            animals[i].Call();
        }

        Console.ReadKey();
    }
}

抽象类

抽象类在功能继承方面与基类相同,抽象类同样可以提供变量、属性、方法等完整的封装功能。抽象类的核心区别在于,可使用abstract 关键字标记抽象方法,抽象方法需在子类中强制实现,是一种强制性约定。由于抽象方法在基类未被实现,所以抽象类不能被实例化。

示例如下:

cs 复制代码
public class Program
{
    static void Main(string[] args)
    {
        Animal[] animals = { new Dog(), new Cat() };
        for (int i = 0; i < animals.Length; i++)
        {
            animals[i].Call();
        }

        Console.ReadKey();
    }
}

public abstract class Animal
{
    public abstract void Call();
}

public class Dog : Animal
{
    public override void Call()
    {
        Console.WriteLine("汪汪汪");
    }
}

public class Cat : Animal
{
    public override void Call()
    {
        Console.WriteLine("喵喵喵");
    }
}

抽象类同样可以用基类变量引用子类实例,即需要基类的功能继承,又需要与子类强制约定方法时,可采用抽象类。

接口

接口是纯方法定义,无任何功能实现。接口同样无法被实例化。接口的核心作用在于为不同的子类约定了接口,这些接口必须在子类中实现。示例如下:

cs 复制代码
public class Program
{
    static void Main(string[] args)
    {
        IAnimal[] animals = { new Dog(), new Cat() };
        for (int i = 0; i < animals.Length; i++)
        {
            animals[i].Call();
        }

        Console.ReadKey();
    }
}

public interface IAnimal
{
    public void Call();
}

public class Dog : IAnimal
{
    public void Call()
    {
        Console.WriteLine("汪汪汪");
    }
}

public class Cat : IAnimal
{
    public void Call()
    {
        Console.WriteLine("喵喵喵");
    }
}

与基类、抽象类相同,同样可以用接口类型变量引用子类实例,提供了统一的持有变量。不同在于接口类内部只能定义方法和属性,不能持有变量。

归纳总结

  • **基类:**可实例化,有自己的变量、属性、方法,完整的独立功能。子类可复用其功能,对子类无强约束。只在功能继承时选择使用。
  • **抽象类:**不可实例化,有自己的变量、属性、方法,完整的独立功能。子类可复用其功能,对子类有强制方法约定,在子类中实现约定方法。在需要功能继承,且需要强制约定子类接口时选择使用。
  • **接口:**不可实例化,只做接口约定,无变量和方法实现。子类无复用功能,强制约定子类的方法,在子类中实现约定方法。在无需功能继承,需强制约定子类接口时选择使用。
相关推荐
遇见~未来11 小时前
JavaScript构造函数与Class终极指南
开发语言·javascript·原型模式
foundbug99911 小时前
基于MATLAB的TDMP-LDPC译码器模型构建、仿真验证及定点实现
开发语言·matlab
X***078812 小时前
从语言演进到工程实践全面解析C++在现代软件开发中的设计思想性能优势与长期生命力
java·开发语言
毕设源码-钟学长12 小时前
【开题答辩全过程】以 基于Python的车辆管理系统为例,包含答辩的问题和答案
开发语言·python
CCPC不拿奖不改名12 小时前
数据处理与分析:数据可视化的面试习题
开发语言·python·信息可视化·面试·职场和发展
液态不合群12 小时前
线程池和高并发
开发语言·python
小镇学者12 小时前
【c++】C++字符串删除末尾字符的三种实现方法
java·开发语言·c++
SmartRadio12 小时前
在CH585M代码中如何精细化配置PMU(电源管理单元)和RAM保留
linux·c语言·开发语言·人工智能·单片机·嵌入式硬件·lora
智慧地球(AI·Earth)13 小时前
Codex配置问题解析:wire_api格式不匹配导致的“Reconnecting...”循环
开发语言·人工智能·vscode·codex·claude code
Ralph_Y13 小时前
C++虚继承
开发语言·c++