c# - 了解接口(interface) V 类

标签 c# .net vb.net oop

嗨,我知道这是一个老生常谈的问题,但在阅读了以下帖子后 What is the difference between an interface and a class, and why I should use an interface when I can implement the methods directly in the class?我很难理解为什么真的需要使用接口(interface)。很抱歉这里的基本问题,但是当我将理论作为接口(interface)和类之间的契约时,我似乎看不出它有多大用处。我知道它可以帮助您轻松创建对象,但我觉得我错过了一些东西。

我在这里和整个互联网上阅读了很多关于如何使用接口(interface)的帖子,但有一半时间我觉得如果你创建一个类并继承它会不会做同样的事情?我在这里错过了什么?

最佳答案

为什么要接口(interface)?

你开车吗?如果没有,我假设您知道驾驶汽车通常需要什么(方向盘、加速器、制动器)。其余答案假设您驾驶汽车并且拥有与我不同品牌的汽车。

你开过我的车吗?不会。但是如果获得访问权限,您是否可以在无需学习如何驾驶我的汽车的情况下驾驶我的汽车?是的。
这同样适用于我。我从来没有开过你的车,但我可以驾驶它而不需要学习如何驾驶它。

这是为什么呢? 因为所有汽车共享相同的界面。方向盘, throttle 在右边,刹车在中间。没有两辆汽车是完全一样的,但它们的制造方式使驾驶员与任何汽车之间的互动完全相同。

将其与 F16 战斗机进行比较。能够驾驶汽车并不意味着您能够驾驶喷气式飞机因为它的界面不同。它没有方向盘,没有 throttle /刹车踏板。

主要好处很明显:驾驶员无需单独学习如何驾驶每辆车。

现在,为了完成类比,汽车的一般概念是一个接口(interface),而具体的汽车是类。主要好处很明显:您不需要为每个类似的类编写自定义代码。


一个实际的例子

public class BMW 
{
    public SteeringWheel SteeringWheel { get; set; }
    public Pedal Accelerator { get; set; }
    public Pedal Brake { get; set; }
}

public class BMWDriver
{
    public void ParticipateInRace(BMW myBMW) 
    {
        myBMW.Accelerator.Press();

        myBMW.SteeringWheel.TurnLeft();
        myBMW.SteeringWheel.TurnRight();

        myBMW.Accelerator.Release();
        myBMW.Brake.Press();

        myBMW.Brake.Release();
    }
}

这个司机只会开宝马。

public class Audi 
{
    public SteeringWheel SteeringWheel { get; set; }
    public Pedal Accelerator { get; set; }
    public Pedal Brake { get; set; }
}

public class AudiDriver
{
    public void ParticipateInRace(Audi myAudi) 
    {
        myAudi.Accelerator.Press();

        myAudi.SteeringWheel.TurnLeft();
        myAudi.SteeringWheel.TurnRight();

        myAudi.Accelerator.Release();
        myAudi.Brake.Press();

        myAudi.Brake.Release();
    }
}

这个司机只会开奥迪。

但实际上,司机可以驾驶任何汽车(有一个方向盘和两个踏板)。

那么我们如何告诉编译器可以使用任何汽车呢?我们为他们提供了一个共同点:界面。

public interface ICar
{
    SteeringWheel SteeringWheel { get; }
    Pedal Accelerator { get; }
    Pedal Brake { get; }
}

public class BMW : ICar { /* same as before */ }

public class Audi : ICar { /* same as before */ }

public class Driver
{
    public void ParticipateInRace(ICar anyCar)
    {
        anyCar.Accelerator.Press();

        anyCar.SteeringWheel.TurnLeft();
        anyCar.SteeringWheel.TurnRight();

        anyCar.Accelerator.Release();
        anyCar.Brake.Press();

        anyCar.Brake.Release();
    }
}

我们现在有一个更通用的Driver,他能够驾驶任何有一个方向盘和两个踏板的汽车。


为什么不继承?

half of the time I am like well if you create a class and inherit it would it not do the same thing? what am I missing here?

在某些情况下,继承会起作用。但是,继承通常是一个较差的解决方案,尤其是当您进入更复杂的代码库或更高级的体系结构时。

别担心,所有开发人员都曾经喜欢继承,然后需要学会不要将继承用作万能药。这是开发人员正常生命周期的一部分:)

最大的原因之一是不能从多个类派生,但可以实现多个接口(interface)

假设我们可以进行三种类型的运动

public class Runner 
{  
    public void Run() { /* running logic */ } 
}

public class Swimmer
{  
    public void Swim() { /* swimming logic */ } 
}

public class Cyclist
{  
    public void Cycle() { /* cycling logic */ } 
}

现在我们需要创建一项专门的运动,例如运行。篮球。

public class BasketBallPlayer : Runner 
{ 
    public void ThrowBall() { /* throwing logic */ }

    // Running is already inherited from Runner
}

很好,还没有问题。但是现在,我们需要创建一个铁人三项类,它包含所有三种运动(运行、游泳、骑自行车)

public class Triathlete: Runner, Swimmer, Cyclist { ... }

这就是编译器崩溃的地方。它拒绝让你同时继承多个基类。原因比这个答案可以深入得多,如果您想了解更多信息,请谷歌搜索。

但是,如果我们使用接口(interface):

public interface IRunner
{
    void Run();
}

public interface ISwimmer
{
    void Swim();
}

public interface ICyclist
{
    void Cycle();
}

那么编译器会允许这样做:

public class Triathlete: IRunner, ISwimmer, ICyclist 
{ 
    public void Run() { /* running logic */ } 

    public void Swim() { /* swimming logic */ } 

    public void Cycle() { /* cycling logic */ } 
}

这就是接口(interface)通常击败继承的原因(以及其他原因)。

接口(interface)通常更好的原因有很多,但这是最重要的一个。如果您需要更多解释,请谷歌搜索,我无法深入研究所有内容以获得 StackOverflow 答案。

关于c# - 了解接口(interface) V 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58410210/

相关文章:

WPF VB DataGridCombox DataGridRow

vb.net - 对组合框中的日期进行排序

c# - 如何在 C# 中将 12 位整数转换为十六进制字符串?

c# - 使用同一个库的两个不同版本

c# - 输入字符串的格式不正确

c# - 如何作为委托(delegate)传递属性?

c# - 正则表达式匹配以逗号分隔的列表,末尾没有逗号

c# - 在 C# 中通过 comport 将位图图像打印到 pos 打印机

c# - 在毫秒内将 Deedle 帧保存到 csv 文件

c# - 双字结果的高​​效长乘法