【问题标题】:C#, Using InterfaceC#,使用接口
【发布时间】:2012-04-29 23:26:57
【问题描述】:

我正在尝试使用接口类,但我对接口方法参数有疑问。

我有一个接口类让子类使用特定的方法。 但是子类需要不同数量的方法参数。

例子,

public interface IPayment
{
  void MakePayment();
}

并在子类中定义 MakePayment 方法。

public class PayPay : IPayment
{
  public void MakePayment(string a); // it needs only one parameter
}

public class Google : IPayment
{
  public void MakePayment(string a, int b); // it needs two parameters.
}

如上例,如何修改我的接口类?

谢谢!

【问题讨论】:

  • 接口和该接口的所有实现需要具有相同的签名(即相同的参数列表)。真的没有办法。
  • 除此之外,“接口类”是矛盾的; “接口类型”或只是“接口”会更好。
  • 额外的参数是什么?它们是否更适合传递给 GooglePaymentProvider 构造函数?

标签: c# asp.net interface


【解决方案1】:

干净的方法可以是简单地使用PaymentParameters 类并使用称为public void MakePayment(PaymentParameters params); 的单个方法

【讨论】:

  • 我不会说那是干净的,恰恰相反。该参数类基本上需要知道所有实现IPayment 的类,以便为每个实现提供有意义的值。
  • 您可以为每个支付类子类化它,然后每个支付类都必须检查它是否通过了它所期望的。您也可以通过在接口上使用“为我创建一个参数类”方法来实现这一点,前提是您可以根据它具有的属性动态填充它,例如通过您的网络框架。但是我不确定我是否 100% 喜欢这个。
  • 这个类可以定义默认值。此外,该方法在未来变得高度可维护..
  • 对此的主要问题是,您必须在 PaymentParameters 中有未使用/未填充的值,或者必须将子类转换为 ala (PayPalParameters) 参数。无论哪种方式,它都不干净。那是因为实现接口的东西应该有相同的签名......在这种情况下很糟糕。
【解决方案2】:

更改您的界面以使用包含每个不同服务可能需要的所有参数的 PaymentParameters 类。

public interface IPayment 
{ 
   void MakePayment(PaymentParameters p);   
} 

public class PaymentParameters{
    public string A { get; set; }
    public int B { get; set; }
}

您的 GooglePayPay 实现将仅使用来自 PaymentParameters 的所需参数。

【讨论】:

  • -_-' 从来没有想过这个解决方案。
  • @FrancisP 伟大的思想是否相同? :) 当我输入此内容时,我从未收到任何“加载新答案”通知。对于它的价值,我确实支持你。
【解决方案3】:

好吧,接口的原则是不了解实现。所以接口的调用者不会知道它是不是PayPay子类的Google,总是会调用同一个方法。

但是如果你有更复杂的参数,你应该使用IPaymentParameters和这个原型的方法

public interface IPayment
{
     void MakePayment(IPaymentParameters parameters);
}

还有两个实现GooglePayementParametersPayPayPaymentParameters

【讨论】:

  • 问题是调用者需要始终传递正确的支付参数,这意味着他们需要知道哪个类在实现接口,这违背了使用接口的目的。
  • 嗯,这取决于你是否使用注入以及谁实例化谁......这是一个更复杂的情况,应该从设计的大局中解决。
【解决方案4】:

您的PayPayGoogle 类是否代表描述付款所需的数据?通常,支付类应该代表支付。如果该类的工作是处理付款,它的名称可能应该类似于PaymentProcessor,其接口类似于IPaymentProcessor(或者实际上是IPaymentService,或类似的名称)。

如果支付类代表实际支付,那么该类不应该需要其MakePayment() 方法的任何参数;相反,它会依赖实例数据来描述正在进行的付款。

或者,你可以有这样的东西(仍然使用Payment 来描述付款本身):

interface IPaymentProcessor<T> where T : IPayment
{
    void ProcessPayment(T payment);
}
class PayPayPaymentProcessor : IPaymentProcessor<PayPay>
{
    void ProcessPayment(PayPay payment) { /* some implementation here */ }
}
class PayPayPaymentProcessor : IPaymentProcessor<Google>
{
    void ProcessPayment(Google payment) { /* some implementation here */ }
}

我可能会将这些类命名为 PayPayPaymentGooglePayment,以便更清楚地表示类型:

class PayPayPaymentProcessor : IPaymentProcessor<PayPayPayment>
{
    void ProcessPayment(PayPayPayment payment) { /* some implementation here */ }
}
class PayPayPaymentProcessor : IPaymentProcessor<GooglePayment>
{
    void ProcessPayment(GooglePayment payment) { /* some implementation here */ }
}

请注意,这与其他人建议的使用PaymentParameters 类的方法非常相似,但它更符合单一职责原则。在 Brian Cauthon 的回答中,PaymentParameters 类必须为任何类型的支付保留所有可能参数的联合;在这里,参数类型可以(并且应该)特定于它们所代表的付款需求。

【讨论】:

    【解决方案5】:

    你可以定义两个接口,也可以使用下面的;

    public interface IPayment
    {
        void MakePayment(string a, int b=0);
    }
    

    当你只传递字符串参数时,该方法会将b设置为0;你可以忽略它。

    【讨论】:

      【解决方案6】:

      如果您使用 .NET 4.0,则可以为您的接口方法提供默认值

      public interface ITest{
      void Function(stirng s1, string s2 = "");
      }
      

      【讨论】:

        【解决方案7】:

        直接来自 MSDN -

        接口仅包含方法、委托或事件的签名

        方法的签名由方法的名称及其每个形式参数的类型和种类(值、引用或输出)组成 >,按从左到右的顺序考虑

        如果您不提供方法的实现(包括每个参数的类型和种类),那么您还没有真正“实现”接口。

        祝你好运! :)

        格伦

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-29
          • 1970-01-01
          • 2014-11-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-03-07
          相关资源
          最近更新 更多