Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 理解接口和类_C#_.net_Vb.net_Oop - Fatal编程技术网

C# 理解接口和类

C# 理解接口和类,c#,.net,vb.net,oop,C#,.net,Vb.net,Oop,嗨,我知道这是一个很容易回答的问题,但是在阅读了下面的文章之后,我很难理解为什么需要使用界面。对于这里的基本问题很抱歉,但是当我把这个理论作为接口和类之间的契约时,我似乎看不出它有多有用。我知道它可以帮助你轻松地创建对象,但我觉得我遗漏了一些东西 我在这里和互联网上读了很多关于如何使用接口的帖子,但有一半的时间我觉得如果你创建一个类并继承它,它会不会做同样的事情?我错过了什么 一个场景,您(整个算法的创建者)根本不知道如何提前实现 要将其转换为现实生活场景,请执行以下操作: FxCop+Styl

嗨,我知道这是一个很容易回答的问题,但是在阅读了下面的文章之后,我很难理解为什么需要使用界面。对于这里的基本问题很抱歉,但是当我把这个理论作为接口和类之间的契约时,我似乎看不出它有多有用。我知道它可以帮助你轻松地创建对象,但我觉得我遗漏了一些东西

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

一个场景,您(整个算法的创建者)根本不知道如何提前实现

要将其转换为现实生活场景,请执行以下操作: FxCop+StyleCop都使用访问者模式来扫描代码。因此,在本例中,工具(FxCop)的创建者拥有一些基本代码,这些代码与某些UI/CLI相耦合,并期望扫描结果中具有某些属性,如严重性/问题等

虽然FxCop附带默认规则,但作为最终客户,您也可以根据自己的喜好扩展这些规则。FxCop实现这一点的唯一方法是依赖polymorpishm接口/抽象类

因此,FxCop工具需要一个规则实例来检测某些东西并报告成功或失败

但是您的组织可能有一个只有您需要的自定义规则。假设它是这样的:我们所有的名称空间都必须以myorg.mytool开头

这是一个必须使用抽象的例子(不能只在类中预先实现代码),因为Microsoft对您在组织中实施的自定义代码规则一无所知

另一个例子是域驱动设计中域和基础结构代码的分离方式

那么,假设您有一个图书收藏应用程序。在那里你可以得到一本书,所有的书都是作者写的,等等

然后,您将有一个域类型调用,类似于BookRepository,您的所有书籍都将被持久化。这有两个方面:1。放置书籍所有处理逻辑的域和2。持久性代码(IO/数据库或其他)

将这两者分开的原因是,这样域逻辑(业务逻辑)就不会与持久性代码纠缠在一起。域代码不想知道一本书是如何持久化的。它只关心你能对一本书做些什么(通过作者获取、购买、出售等)

本例中的接口是在域代码中放置一个名为IBookRepository的接口,然后继续创建单元测试所需的所有代码。在这一点上,你不太关心书是如何存储的——你只关心它们是如何存储的。然后由另一个团队或更高的团队,您可以深入了解有关如何修复该书的详细信息。在数据库、缓存或其他地方。持久性代码也可以在不涉及域代码的情况下发展,域代码是持续发布原则的一个组成部分:尽可能小的更新。换句话说,它允许您根据业务代码发布基础架构更新。可能是你的应用程序运行得很好,但你不想更新数据库驱动程序

抽象类是介于接口和类之间的东西,但应该像接口一样使用/它们在使用上比类更接近接口

** 最后,使用接口的另一个原因是,可以将接口视为方面,并且可以将多个接口(方面)应用于单个类(多重继承)几乎没有摩擦,而将其放在类中会迫使您执行单个继承,这可能会导致较大且过于复杂的继承层次结构


希望它能在本质上对您有所帮助,并且在每种情况下,我都能尽可能少地说几句话:

  • 当您有不同的实体共享时,应使用摘要 普通行为
  • 当您希望不同实体能够使用相同的代码
    工作时,应使用接口
例如,在以下情况下,您将使用“摘要”:

您想创建一个处理动物的应用程序。 创建一个抽象类
Animal
,其中包含一些字段
NoLegs
HasTail
NoEyes
。 您创建了一个
、一个
和一个
熊猫
类,所有这些都是从
动物
继承的。 现在你有了3个类,但是在另外1个类中定义了共享代码,因为它们都有这些描述特征

现在进入界面: 在项目中的服务中,您创建了一个名为“StartRunning”的方法。 该方法的定义为:

public void StartRunning(List<ICanRun> thingsThatRun)
{
    thingsThatRun.forEach(t => t.StartRunning());
}
我希望这个例子有助于

为什么选择接口? 你开车吗?如果没有,我想你知道开车通常需要什么(方向盘、加速器、制动器)。答案的其余部分假设你驾驶一辆与我不同品牌的汽车

你开过我的车吗?没有。但是如果你有权限,你能不用学习如何驾驶我的车就可以驾驶我的车吗?是的。
这同样适用于我。我从来没有开过你的车,但我可以不用学开车就能开

为什么呢因为所有汽车共享相同的界面。方向盘,右边是加速器,中间是刹车。没有两辆车是完全相同的,但它们的构造方式使驾驶员和任何一辆车的交互作用完全相同

将其与F16战斗机进行比较。驾驶汽车并不能让你驾驶喷气式飞机,因为它的界面不同。它没有方向盘,没有加速器/制动踏板

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

现在,为了完成这个类比
List<ICanRun> runableThings = new List<ICanRun>(){new Dog(), new Cat(), new Bike()};
StartRunning(runableThings);
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();
    }
}
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 { ... }
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 */ } 
}