C#实现了不同的签名

本文关键字:实现 | 更新日期: 2023-09-27 17:58:24

我想这也是一个设计问题。当重写签名具有不同的签名类型时,是否可以从接口重写方法?

例如,假设我想要两个不同的类,它们应该具有以下内容:

 interface IProtocolClient
 {
    void connect(Type1 t1, Type2 t2, Type3 t3);
 }

是否有可能阻止种族间的竞争,但有一个不同的参数集?

 class A : IProtocolClient {
   public void connect( Type1 t1, Type2 t2, Type3 t3 ) {}
 }
 class B : IProtocolClient {
   public void connect( Type1 t1, Type2 t2, Type3 t3, Type4 t4 ) {}
 }

或者我应该通过创建一个基类来解决这个问题,然后在类B中创建一个包装方法,例如:

 class B : IProtocolClient {
   public void connect( Type1 t1, Type2 t2, Type3 t3, Type4 t4)
   {
      // do what is needed with t4 to customize and then ...
      connect(t1,t2,t3);
   }
   public void connect( Type1 t1, Type2 t2, Type3 t3) {}
 }

C#实现了不同的签名

接口是类"签署"的"契约",该类必须实现定义的接口。您的第二种方法是使用特定于类的方法来扩展接口指定的类,然后调用接口方法,这是一个合理的解决方案,但这当然意味着您不能将接口用作可能无法达到目的的类型。

您的最后一个选项是唯一可能工作的选项(因为它是唯一一个在两个类中正确实现接口的选项)。

不过,请记住,任何通过接口访问类的人都只能访问connect(Type1 t1, Type2 t2, Type3 t3)方法,这完全消除了您提供其他方法的事实(除非人们也可以直接访问该类型)。

不,这不是重写,而是重载。重载永远不会重写,你必须实现原始的,然后提供一个调用接口实现的重载。

如果你实现了一个接口,你必须包括任何方法、属性等。这就是接口的意义:它们是代码契约。这并不能阻止您使用不同的参数签名重载方法。但是,如果您不需要实现指定的方法,那么您可能根本不需要接口。

我认为要么使用选项2,要么更改接口以接受类型列表。

遗憾的是,如果您没有完全实现接口,编译会对您大发雷霆。

然而,我认为下面的实现非常干净。

public interface ITestClass
{
    void Test(Type a, Type b);
}
public class TestClass : ITestClass
{
    //implement the interface here
    public void Test(Type a, Type b)
    {
        Test(a, b);
    }
    //you actual implementation here
    public void Test(Type a, Type b, Type c = null)
    {
        //implementation
    }
}

更新如果你要列出一系列的东西,那么这个实现是首选的:

    public void Test(params Type[] parameters)
    {
        //sample usage
        Type one, two, three, four;
        Test(one, two);
        Test(one, two, three, four);
    }

如果您希望实现IProtocolClient的所有类都知道这两个签名,那么将重载签名添加到代理

public interface IProtocolClient
 {
    void connect(Type1 t1, Type2 t2, Type3 t3);
    void connect( Type1 t1, Type2 t2, Type3 t3, Type4 t4)
 }

如果你想在某些实现中隐藏该签名,你可以显式地实现它

    class A : IProtocolClient {
       public void connect( Type1 t1, Type2 t2, Type3 t3 ) {}
       void  IProtocolClient.connect(Type1 t1, Type2 t2, Type3 t3, Type4 t4){
        throw new NotImplementedException();
       }     
 }

但是,如果您只需要在一个实例类的范围内使用扩展签名,那么上一个示例是正确的,其中classB实现了原始接口,然后添加了重载签名。然而,在这种情况下,任何将classB转换为IProtocolInterface的人都不会看到第二个签名。

如果所有类型都相同,或者有一个公共基类或接口,如IConnectable,你可以使用params关键字:

http://msdn.microsoft.com/en-us/library/w5zay9db.aspx

如果将所有参数作为对象传递,则可以派生参数类,然后在实现的方法中强制转换它。

    interface IProtocolClient
    {
        void connect(ParamType p);
    }
    class ParamType
    {
        public Type1 t1 { get; set; }
        public Type2 t2 { get; set; }
        public Type3 t3 { get; set; }
    }

=>

    class A : IProtocolClient
    {
        public void connect(ParamType p)
        {
            //do something with p.t1, p.t2, p.t3
        }
    }
    class B : IProtocolClient
    {
        public void connect(ParamType p)
        {
            var p2 = p as DerivedParamType;
            if (p2 == null)
                throw new ApplicationException("p must be of type DerivedParamType");
            //do something with p2.t1, p2.t2, p2.t3, p2.t4
        }
    }
    class DerivedParamType : ParamType
    {
        public Type4 t4 { get; set; }
    }

hth