C#:具体类=>抽象类=>接口的变化过程详解

文章目录


简单复习继承与多态

下面,我用一个交通工具的例子来快速复习一下 .
1.首先我定义一个基类Vehicle,代表交通工具的总称.里面定义了一个可被重写的成员方法Run.

csharp 复制代码
    class Vehicle
    {
        public virtual void Run()
        {
            Console.WriteLine("Vehicle is running");
        }
    }

2.定义两个派生类继承Vehicle这个基类,然后用override进行重写,覆盖掉之前的基类.

csharp 复制代码
    class Car : Vehicle
    {
        public override void Run()
        {
            Console.WriteLine("Car is running");
        }
    }
    class Truck : Vehicle
    {
        public override void Run()
        {
            Console.WriteLine("Truck is running");
        }
    }

Main方法:

csharp 复制代码
    class Program
    {
        static void Main(string[] args)
        {
            Vehicle vehicle = new Vehicle();
            Car car = new Car();
            Truck truck = new Truck();  //定义三个对象

            vehicle.Run();
            car.Run();
            truck.Run();
        }
    }

实验结果

通过上面的代码和结果可以知道,Run方法继承到派生类Car,被我们重写之后,调用Run所运行的就是Car is running. override重写的方法将virtual方法覆盖.
我们如果想继承Car这个类并对他的Run进行重写的话,也是一样,用override进行重写.

csharp 复制代码
    class RaceCar:Vehicle
    {
        public override void Run()
        {
            Console.WriteLine("RaceCar is running");
        }
    }

具体类

上面我们所创建的就是具体类,每个方法都有实现.

csharp 复制代码
    class Vehicle
    {
        public virtual void Run()
        {
            Console.WriteLine("Vehicle is running");
        }
    }

那么问题来了,我们在日常生活中,总不会说出交通工具在跑吧?基类的这个Run的实现显得没有那么必要,只会增加我们的工作量.
没错,问题的解决方法就是抽象类

抽象类及成员

使用

csharp 复制代码
    abstract class Vehicle
    {
        public abstract void Run();
    }
    class Car : Vehicle
    {
        public override void Run()
        {
            Console.WriteLine("Car is running");
        }
    }

把基类的Run方法的代码块去掉,然后在方法体和类前面加个abstract关键字.声明这是一个抽象类.
其他不需要修改

语法

1.何为抽象?就是不具体.所以我们不可以抽象具体的数据成员和字段

2.抽象类不能被实例化.(不具体的东西怎么能被实际表示出来呢?)

3.因为抽象类不能被实例化,所以抽象类天生就是要被继承的.抽象类因为类里面有抽象方法不能被实例化.所以派生类在继承抽象类时必须把抽象类欠下的债还回去.(把抽象成员表示具体)

派生类Car在继承Vehicle时,把所有的抽象成员都用override重写了.所以编译通过.
而truck没有把抽象成员全部重写,编译失败

由上面的代码我们也可以看出,派生类要实现抽象类的抽象成员必须用override重写.

那么问题又来了,这种实现了一部分的抽象类是什么?

这种实现了一半的派生类自己也是抽象类. (毕竟还欠着债呢)

4.抽象类可以包含抽象成员和具体成员

csharp 复制代码
    abstract class Vehicle
    {
        public int size = 10; //具体成员
        public abstract int Speed{ get; set; }
        public abstract void Run();
    }

总结:abstract 抽象类 :为复用而生,不能实例化,专门作为基类,未完全实现逻辑的类(方法没实现全)

接口

抽象类到接口的进化

csharp 复制代码
abstract class VehicleBase
{
    abstract public void Stop();
    abstract public void Run();
}

这是一个抽象类,里面声明两个抽象方法,Run与Stop.
问题来了,难道不觉得重复写abstract public 让代码显得很臃肿吗?
所以,接口来了.

csharp 复制代码
interface IVehicleBase
{
    void Stop();
    void Run();
}

把abstract public都去掉,抽象类名前面的关键字换成interface接口.

我们来给接口下一个定义:接口是完全未实现逻辑的类,纯虚类,只有函数成员,且都为public

换句话说:接口是函数成员全都是abstract public类型的抽象类.

相关推荐
用户788477316342 小时前
WinForms 迁移 WPF:Upgrade Assistant 覆盖 30%,剩下 70% 我手写了六周
c#
another heaven4 小时前
【C/C++ Ranges 是零开销抽象吗?拆开管道、惰性求值和编译期膨胀】
c语言·开发语言·c++
SomeOtherTime5 小时前
Rust 闭包语法和原理(AI回答)
开发语言·后端·rust
apcipot_rain5 小时前
C++转Java日记(10)
java·开发语言
总要学点什么6 小时前
第105篇:三维特效-流动图片墙体效果——让箭头沿墙长滚,它俩竟是同一份代码
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
xiaoye-duck6 小时前
《C++ 项目:手写大模型接入 SDK》会话模块整合:内存 SessionManager 与 DataManager 持久化联动
开发语言·数据库·c++·语言模型
寂寞的船7 小时前
【Unity知识速递】第13期 Unity 内存泄漏排查实战:从 Memory Profiler 到 Lua 引用泄漏的生产级全链路诊断
unity·junit·c#·游戏引擎·lua
Funlang7 小时前
龙芯上的 Fun:从跑起来到机器码
开发语言·龙芯
总要学点什么8 小时前
第104篇:三维特效-流动墙体效果——让贴图沿墙流动,它却只肯走一条对角线
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
旖旎夜光8 小时前
【C++ 基础入门】C++11 新特性(中):右值引用、移动语义与完美转发
开发语言·c++·笔记·学习