【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("喵喵喵");
    }
}

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

归纳总结

  • **基类:**可实例化,有自己的变量、属性、方法,完整的独立功能。子类可复用其功能,对子类无强约束。只在功能继承时选择使用。
  • **抽象类:**不可实例化,有自己的变量、属性、方法,完整的独立功能。子类可复用其功能,对子类有强制方法约定,在子类中实现约定方法。在需要功能继承,且需要强制约定子类接口时选择使用。
  • **接口:**不可实例化,只做接口约定,无变量和方法实现。子类无复用功能,强制约定子类的方法,在子类中实现约定方法。在无需功能继承,需强制约定子类接口时选择使用。
相关推荐
ZK_H12 小时前
半导体工艺流程
java·c语言·开发语言·计算机网络·金融
计算机安禾12 小时前
【数据结构与算法】第39篇:图论(三):最小生成树——Prim算法与Kruskal算法
开发语言·数据结构·c++·算法·排序算法·图论·visual studio code
liliangcsdn12 小时前
sentence-transformer如何离线加载和使用模型
开发语言·前端·php
Crazy________12 小时前
4.10dockerfile构建镜像
java·开发语言
fish_xk12 小时前
c++内存管理
开发语言·c++·算法
独特的螺狮粉13 小时前
城市空气质量简易指数查询卡片:鸿蒙Flutter框架 实现的空气质量查询应用
开发语言·flutter·华为·架构·harmonyos
网域小星球13 小时前
C语言从0入门(八)|函数基础:封装、调用与参数传递精讲
c语言·开发语言
东宇科技13 小时前
如何使用js进行抠图。识别商品主体
开发语言·javascript·ecmascript
Dxy123931021613 小时前
Python使用PyEnchant详解:打造高效拼写检查工具
开发语言·python
网域小星球13 小时前
C 语言从 0 入门(十五)|综合小项目:菜单交互与简易功能实现
c语言·开发语言·交互