C# 抽象类和接口详解

参考视频链接:https://www.bilibili.com/video/BV13b411b7Ht?p=27&vd_source=10065785c7e10360d831474364e0d3e3
代码的进化与重构,从基本代码的讲解到逐步抽象成抽象类和接口。

最初定义

最初定义两个类Car 和 Truck

namespace InterfaceAPPLication
{
    class Car
    {
        public void Run()
        {
            Console.WriteLine("Car is Running");
        }
        public void Stop() 
        {
            Console.WriteLine("Stopped");
        }
    }

    class Truck
    {
        public void Run()
        {
            Console.WriteLine("Truck is Running");
        }
        public void Stop()
        {
            Console.WriteLine("Stopped");
        }
    }
}

利用继承改进

两个类具有重复的代码Stop()方法,不符合代码不重复出现的规则,对代码进行改进,将两个类继承自一个类 Vehicle

namespace InterfaceAPPLication
{
    class Vehcile
    {
        public void Stop()
        {
            Console.WriteLine("Stopped");
        }
    }
    class Car:Vehcile
    {
        public void Run()
        {
            Console.WriteLine("Car is Running");
        }
    }

    class Truck
    {
        public void Run()
        {
            Console.WriteLine("Truck is Running");
        }
    }
}

对方法进一步改进

继续观察Run方法,对Run方法进行改进:

namespace InterfaceAPPLication
{
    class Vehcile
    {
        public void Stop()
        {
            Console.WriteLine("Stopped");
        }

        public void Run(string type)
        {
            if (type == "Car")
            {
                Console.WriteLine("Car is Running");
            }else if(type == "Truck")
            {
                Console.WriteLine("Truck is Running");
            }
           
        }
    }
    class Car:Vehcile
    {
        
    }

    class Truck:Vehcile
    {
       
    }
}

利用虚函数进行改进

但是当有新的类从Vehcile派生的话,就需要多Vehicle.Run(string type)函数体进行扩充,不符合设计原则中的封闭原则。替代方式,使用virtual虚函数修饰Run方法,派生类对Run方法进行重写。

namespace InterfaceAPPLication
{
    class Vehcile
    {
        public void Stop()
        {
            Console.WriteLine("Stopped");
        }

        public virtual void Run(string type)
        {
            Console.WriteLine("Vehcile is Running");
        }
    }
    class Car:Vehcile
    {
        public override void Run(string type)
        {
            Console.WriteLine("Car is Running");
        }
    }

    class Truck:Vehcile
    {
        public override void Run(string type)
        {
            Console.WriteLine("Truck is Running");
        }
    }
}

利用抽象进行改进

基类Vehicle的Run方法被派生类重新实现,所以Run方法的函数体是没有意义的,所以可以修改为abstract方法,同时 Vehicle类为抽象类;

namespace InterfaceAPPLication
{
    abstract class Vehcile
    {
        public void Stop()
        {
            Console.WriteLine("Stopped");
        }

        public abstract void Run(string type);
    }
    class Car:Vehcile
    {
        public override void Run(string type)
        {
            Console.WriteLine("Car is Running");
        }
    }

    class Truck:Vehcile
    {
        public override void Run(string type)
        {
            Console.WriteLine("Truck is Running");
        }
    }
}

Vehcile抽象类包含的方法不全是抽象方法,当一个抽象类全部都是抽象方法的时候,IVechile类就是一个全是抽象方法的类 。可以看到Vehcile :继承IVechile,其中重写了 Filled() 和 Stop()方法,没有重写Run(string type)方法,不需要声明,默认继承了,然后Run(string type)在Car和Truck类中实现。

 abstract class IVechile
    {
        public abstract void Filled();
        public abstract void Run(string type);
        public abstract void Stop();
    }
    abstract class Vehcile : IVechile
    {
        public override void Stop()
        {
            Console.WriteLine("Stopped");
        }
        public override void Filled()
        {
            Console.WriteLine("Pay and Filled");
        }

    }
    class Car : Vehcile
    {
        public override void Run(string type)
        {
            Console.WriteLine("Car is Running");
        }
    }

    class Truck : Vehcile
    {
        public override void Run(string type)
        {
            Console.WriteLine("Truck is Running");
        }
    }

利用接口进行改进

IVechile类就是一个全是抽象方法的类 ,

 abstract class IVechile
    {
        public abstract void Filled();
        public abstract void Run(string type);
        public abstract void Stop();
    }

抽象类的抽象方法需要被派生类实现,所以默认是public abstract, 改为接口后方法就不需要修饰符了:(接口的命名方式大写英文字母 I+name)

 interface IVechile
    {
        void Filled();
        void Stop();
        void Run(string type);
    }

注意,在对接口中方法进行实现的时候,没有实现的方法,需要在抽象类中注明是待实现的抽象方法

 interface IVechile
    {
        void Filled();
        void Stop();
        void Run(string type);
    }
    abstract class Vehcile : IVechile
    {
        public  void Stop()
        {
            Console.WriteLine("Stopped");
        }
        public  void Filled()
        {
            Console.WriteLine("Pay and Filled");
        }
        abstract public void Run(string type);
    }

最后给出最终的完整代码:

using System;
using System.Collections;
using System.Data;

namespace InterfaceAPPLication
{

    interface IVechile
    {
        void Filled();
        void Stop();
        void Run(string type);
    }
    abstract class Vehcile : IVechile
    {
        public  void Stop()
        {
            Console.WriteLine("Stopped");
        }
        public  void Filled()
        {
            Console.WriteLine("Pay and Filled");
        }
        abstract public void Run(string type);
    }
    class Car : Vehcile
    {
        public override void Run(string type)
        {
            Console.WriteLine("Car is Running");
        }
    }

    class Truck : Vehcile
    {
        public override void Run(string type)
        {
            Console.WriteLine("Truck is Running");
        }
    }

    class Executer
    {
        static void Main(string[] args)
        {
            Vehcile car = new Car();
            car.Run("Car");
            car.Stop();

            Vehcile truck = new Truck();
            truck.Run("Truck");
            truck.Stop();

        }
    }
}

运行结果:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抽象类接口C#中有以下异同点: 相同点: 1. 都不能被实例化,只能通过实现它们的子类或实现类来创建对象。 2. 子类或实现类必须实现抽象类接口中的所有方法才能被实例化。 3. 可以被其他类继承或实现。 异同点: 1. 抽象类是特殊的类,可以包含成员变量、方法、属性等,而接口只能包含方法、属性、事件和索引器的声明。 2. 一个类只能继承一个抽象类,但可以实现多个接口。 3. 抽象类可以有方法的实现,而接口只能有方法的声明。 4. 抽象类可以有字段和构造函数,而接口不能有字段和构造函数。 5. 接口可以被其他接口继承,形成接口的继承链,而抽象类不能被继承。 总结来说,抽象类更适合用于定义一些具有共同特征的类的基类,而接口更适合用于定义一些行为的规范,使得不同的类可以实现这些规范。 #### 引用[.reference_title] - *1* [Java抽象类接口的异同点](https://blog.csdn.net/m0_64742984/article/details/124610167)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [C# 抽象类接口异同](https://blog.csdn.net/Monkey_Xuan/article/details/115915086)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值