抽象类与接口的产生和使用

抽象类与接口的产生和使用

我们以以下代码为例,简述一下抽象类与接口的由来和使用

    class Program
    {
        static void Main(string[] args)
        {
            Car car = new Car();
            car.Run();
            car.Stop();
            car.Fill();
        }
    }
    class Vehicle
    {
        public virtual void Run()
        {
            Console.WriteLine("Vehicle is Running");
        }
        public virtual void Stop()
        {
            Console.WriteLine("Vehicle is Stopped");
        }
        public virtual void Fill()
        {
            Console.WriteLine("Fill Fuel");
        }
    }
    class Car:Vehicle
    {
        public override void Run()
        {
            Console.WriteLine("Car is Running");
        }
        public override void Stop()
        {
            Console.WriteLine("Car is Stopped");
        }
    }
}

我们发现这个例子中,Vehicle类中的Run()和Stop()方法根本没有用到过,而且Vehicle is Running 这种说法太不具体了。
因此我们修改Vehicle类,让Run()和Stop()方法里干脆啥都别写了,反正又用不到

    class Vehicle
    {
        public virtual void Run() { }
        public virtual void Stop() { }
        public void Fill()
        {
            Console.WriteLine("Fill Fuel");
        }
    }

但是{}内空空的啥都不写这不合适吧,干脆把方法体也去掉吧,只留方法名
以下这段代码无法通过编译,只是举例用

    class Vehicle
    {
        public virtual void Run() ;//这样是无法编译的
        public virtual void Stop() ;//这样是无法编译的
        public void Fill()
        {
            Console.WriteLine("Fill Fuel");
        }
    }

Run()和Stop()方法本来就是虚方法(virtual),现在方法体也没了,更虚了,因此诞生了——抽象方法

    abstract class Vehicle
    {
        abstract public void Run();
        abstract public void Stop();
        public void Fill()
        {
            Console.WriteLine("Fill Fuel");
        }
    }

使用时,子类中重写依然是加个override就完事。
抽象类是专门为了做基类而生的,因为抽象类无法实例化,即使抽象类内部有实际的方法,也因为有抽象方法而无法调用所有的方法而报错。
即使有具体方法Fill(),依然不可以实例化。

那么如果这个抽象类特别抽象,抽象到不含有任何实际方法,比如新建一个Vehicle类的父类Tools,具有抽象方法Fill()。

    abstract class Tools
    {
        abstract public void Run();
        abstract public void Stop();
        abstract public void Fill();
    }

在C#中,这种纯抽象类,就是接口。
我们换成接口的写法:

    interface Tools
    {
        void Run();
        void Stop();
        void Fill();
    }

然后我们的代码就形成如下的层次:

namespace Example
{
//程序执行入口
    class Program
    {
        static void Main(string[] args)
        {
            Car car = new Car();
            car.Run();
            car.Stop();
            car.Fill();
        }
    }
//接口,把具体实现方法下放(放到基类)
    interface Tools
    {
        void Run();
        void Stop();
        void Fill();
    }
//基类,把抽象的方法继续下方到派生(可能还是抽象类,也可能是具体类)
    abstract class Vehicle
    {
        abstract public void Run();
        abstract public void Stop();
        public virtual void Fill()
        {
            Console.WriteLine("Fill Fuel");
        }
    }
//派生类(这里是具体类)把抽象方法补充成具体的方法
    class Car:Vehicle
    {
        override public void Run()
        {
            Console.WriteLine("Car is Running");
        }

        public override void Stop()
        {
            Console.WriteLine("Car is Stopped");
        }
    }
}

一般一个项目就是这样的架构,我们也了解了抽象类,接口等等的用法。