在参数 C# 中传递接口

Jon*_*Jon 3 c# parameters interface

图片

传入参数有什么好处?我们可以从中获得什么?目的是什么?

interface IBankAccount
{
    void PayIn(decimal amount);
    bool Withdraw(decimal amount);
    decimal Balance { get; }
}

interface ITransferBankAccount : IBankAccount
{
    bool TranferTo(IBankAccount destination, decimal amount);
}

class CurrentAccount : ITransferBankAccount
{

    public bool TranferTo(IBankAccount destination, decimal amount)
    {
        bool result;
        result = Withdraw(amount);
        if (result)
        {
            destination.PayIn(amount);
        }
        return result;
    }



    public decimal Balance
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    public void PayIn(decimal amount)
    {
        throw new NotImplementedException();
    }





  public bool Withdraw(decimal amount)
    {
        throw new NotImplementedException();
    }
Run Code Online (Sandbox Code Playgroud)

演示代码显示此技术提前致谢

Zoh*_*led 6

好吧,我本来想对克里斯托斯的答案发表评论,但它太长了,所以我将其作为补充答案发布:

要回答这个问题,首先必须了解什么是接口。大多数开发人员会告诉您接口是类的契约。如果你问他们这实际上意味着什么,我不确定他们中的大多数人是否能够向尚未对面向对象编程有基本了解的人解释它。

那么,什么是对接口更好的解释呢?
恕我直言,接口最好从字面上解释 - 它是一个可以与实现该接口的类的实例进行交互的有保证的方法列表。这不是一个完整的列表 - 因为没有什么可以阻止该类在该接口之外添加方法和属性等功能,但是 - 这是重要的部分 -它保证接口上的每个方法、属性、事件或索引器实际上都包含在班上。

为什么这如此重要?它如何让你作为程序员的生活变得更好?
这很重要,因为它意味着您可以使用接口而不是具体的实现。
你为什么想这么做?

  • 因为它使您能够向使用您的方法的任何人公开尽可能少的信息。
  • 因为这意味着所有实现该接口的东西都可以使用这个方法(并且从接口的解释中可以看到,它是保证编译的),意味着使用该方法的限制更少
  • 因为无论谁使用你的方法都不需要了解具体的实现。它只需要知道接口即可使用您的方法。
  • 因为如果您的方法接受类A作为参数,并且后来决定添加B也将使用此方法的类,则您必须编写另一个接受B作为参数的方法。通过使用接口作为方法的参数,您所需要做的就是同时拥有两者AB实现相同的接口(这可能是完全不同的实现),然后简单地传递Aor ,因为通过多态性,B两者都是界面。


Chr*_*tos 5

你实现了一个原则,即

编程到接口,而不是实现。

GoF 在他们的开创性著作《设计模式》中介绍了这一点。坚持这种做法的好处如下:

  • 只要对象遵守接口,客户就不会知道他们使用的特定类型的对象。
  • 客户仍然不知道实现这些对象的类;客户只知道定义接口的抽象类

根据您发布的示例,我们有两个接口:

interface IBankAccount
{
    void PayIn(decimal amount);
    bool Withdraw(decimal amount);
    decimal Balance { get; }
}

interface ITransferBankAccount : IBankAccount
{
    bool TranferTo(IBankAccount destination, decimal amount);
}
Run Code Online (Sandbox Code Playgroud)

该接口IBankAccount由每个银行账户应具有的两种方法和一种属性组成(至少从该接口的作者和她/他试图解决的问题的角度来看)。

具体来说,我们应该能够从银行账户存款 ( PayIn) 和取款 ( Withdraw),最后但并非最不重要的是读取账户余额Balance

关于第二个界面,ITransferBankAccount这表现出只有某些帐户可能具有的行为。这种行为是为了转移资金。我们可以假设有两种银行账户,一种是您可以将钱从一个银行账户转账到另一个银行账户,另一种是您不能,您只能从该特定银行账户存款/取款。这只是与她/他试图解决的这些接口的作者的这个特定问题相关的假设,

甚至在我们继续之前CurrentAccount,接口的好处在第二个接口中很明显!

我们定义了一个行为,这些转账的,我们并不需要的TranferTo方法,因为它是第一个参数的自定义类型像CurrentAccount或其他类型。我们只要求这个方法的第一个参数应该实现接口IBankAccount。只是这个 !这足以让我们转移一些钱,因为我们可以使用该PayIn方法将钱存入帐户。

为什么后者很重要?

例如,假设我们有 3 个银行账户 A、B、C。此外,假设账户 B 和账户 C 在业务方面不同。例如,每当帐户 B 收到一笔钱时,如果我们将它与帐户 C 进行比较,我们应该做一些额外的操作。这意味着为了对此进行建模,我们应该有两个不同的类。BankAccount_BBankAccount_C。除此之外,让我们假设每当我们从 A 提款到任何其他帐户时,我们都必须收取特定费用并应用一些额外的逻辑。这绝对意味着银行账户 A 应该使用另一个类建模。让我们称之为BankAccount_A

如果我们假设所有这些类BankAccount_ABankAccount_BBankAccount_C实现接口IBankAccount和类BankAccount_A实现了接口ITransferBankAccount,那么你可以写这样的代码:

var bankAccountA = new BankAccount_A();

// Deposit $100 in Bank Account A
bankAccountA.PayIn(100);

var bankAccountB = new BankAccount_B();
var bankAccountC = new BankAccount_C();

// Transfer $ 60  to bank account B from A
bankAccountA.TransferTo(bankAccountB, 60);

// Transfer $ 40  to bank account B from A
bankAccountA.TransferTo(bankAccountC, 40);
Run Code Online (Sandbox Code Playgroud)

假设现在你没有遵循这个原则,你想要实现上述功能。在这种情况下,您应该在 class 中定义了两个方法BankAccount_A。一个用于将资金转移到使用 创建的银行帐户,BankAccount_B另一个用于将资金转移到使用创建的银行帐户BankAccount_C。如果您将来对另一个帐户 D 有其他要求怎么办?你应该定义另一种方法等等......这次你应该违反SOLID的原则之一,开放/关闭原则,软件实体......应该对扩展开放,但对修改关闭。如果我们使用了我们已经关闭进行修改的界面:)。