C# interface - implement with different signature
I suppose this is somewhat of a design question too. Is it possible to override a method from an interface when the overriding signature has a different signature type?
For example, lets say that I want two different classes that should have the following:
interface IProtocolClient
{
void connect(Type1 t1, Type2 t2, Type3 t3);
}
Would it be possible to impelemt the interfrace but have a different parameter set?
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 ) {}
}
Or should I approach this by creating a base class instead, and then create a wrapper method in class B such as:
class B : IProtocolClient {
public void connect( Type1 t1, Type2 t2, Type3 t3, Type4 t4)
{
// do what is n开发者_运维百科eeded with t4 to customize and then ...
connect(t1,t2,t3);
}
public void connect( Type1 t1, Type2 t2, Type3 t3) {}
}
An Interface is a 'contract' that your class 'signs up to' and the class must implement the interface as defined. Your second approach to use a class specific method that extends the interface specified class and then calls the interface method is a reasonable solution but of course does mean that you can't use the Interface as a type which could defeat the purpose.
Your last option is the only one that would possibly work (as its the only option that properly implements the interface in both classes).
Remember, though, that anybody accessing the class via the interface will only have access to the connect(Type1 t1, Type2 t2, Type3 t3)
method which completely voids the fact that you provide the other (unless people may access the type directly as well).
No, that is not overriding, it's overloading. Overloading never overrides, you'd have to implement the original then provide an overload that calls the interface implementation.
If you implement an interface, you HAVE to include any methods, properties, etc. That's the point of interfaces: they are code contracts. That doesn't keep you from overloading the methods with different parameter signatures. But if you don't need to implement the method specified then you probably don't need the interface at all.
I'd say either go with option 2 or change the interface to accept a List of types.
Sadly the compile will bark at you if you don't exactly implement the interface.
However, I think the below implementation is pretty clean.
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
}
}
Update If you're going with a list of things then this implementation is preferred:
public void Test(params Type[] parameters)
{
//sample usage
Type one, two, three, four;
Test(one, two);
Test(one, two, three, four);
}
If you want all classes which implement IProtocolClient
to have knowledge of both signatures, then add the overload signature to the proxy
public interface IProtocolClient
{
void connect(Type1 t1, Type2 t2, Type3 t3);
void connect( Type1 t1, Type2 t2, Type3 t3, Type4 t4)
}
If you want to hide that signature in some implementations, you can implement it explicitly
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();
}
}
But if you only need the extended signature within the scope of in one instance class, then your last example was correct, where classB
implements the original interface and then adds the overload signature. In that case however, anyone casting classB
to IProtocolInterface
will not see the second signature.
If all the types were the same, or had a common base class or interface such as IConnectable, you could use the params keyword:
http://msdn.microsoft.com/en-us/library/w5zay9db.aspx
If you pass all parameters as an object, you could derive the parameter class and then cast it in your implemented method.
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
精彩评论