2011-06-03 7 views
2

Je suppose que c'est aussi une question de conception. Est-il possible de remplacer une méthode d'une interface lorsque la signature de remplacement a un type de signature différent?Interface C# - implémenter avec une signature différente

Par exemple, permet de dire que je veux deux classes différentes qui devraient avoir les éléments suivants:

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

Serait-il possible de l'impelemt interfrace mais un jeu de paramètres différent?

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) {} 
} 

Ou devrais-je aborder en créant une classe de base au lieu, puis créer une méthode d'emballage en classe B tels que:

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) {} 
} 

Répondre

3

Une interface est un 'contrat' auquel votre classe adhère et la classe doit implémenter l'interface telle que définie. Votre deuxième approche pour utiliser une méthode spécifique à la classe qui étend la classe spécifiée par l'interface et appelle ensuite la méthode d'interface est une solution raisonnable, mais bien sûr signifie que vous ne pouvez pas utiliser l'interface comme un type qui pourrait aller à l'encontre du but.

1

Si vous implémentez une interface, vous devez inclure toutes les méthodes , propriétés, etc. C'est le but des interfaces: ce sont des contrats de code. Cela ne vous empêche pas de surcharger les méthodes avec différentes signatures de paramètres. Mais si vous n'avez pas besoin d'implémenter la méthode spécifiée, vous n'avez probablement pas besoin de l'interface du tout.

1

Je dirais soit aller avec l'option 2 ou changer l'interface pour accepter une liste de types.

+0

Ils devraient probablement utiliser des médicaments génériques au lieu de la liste , si c'est ce que vous proposez. – jlafay

+0

Ouais à peu près –

2

Votre dernière option est la seule qui pourrait fonctionner (car c'est la seule option qui implémente correctement l'interface dans les deux classes). Souvenez-vous, cependant, que quiconque accède à la classe via l'interface n'aura accès qu'à la méthode connect(Type1 t1, Type2 t2, Type3 t3) qui annule complètement le fait que vous fournissez l'autre (à moins que les utilisateurs ne puissent accéder directement au type).

3

Non, cela ne surcharge pas, c'est la surcharge. La surcharge ne remplace jamais, vous devrez implémenter l'original puis fournir une surcharge qui appelle l'implémentation de l'interface.

+0

Bonne prise et clarification. – mdisibio

0

Malheureusement, la compilation va vous aboyer si vous n'implémentez pas exactement l'interface.

Cependant, je pense que l'implémentation ci-dessous est assez propre.

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 
    } 
} 

Mise à jour Si vous allez avec une liste de choses alors cette mise en œuvre est préféré:

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

Si vous voulez que toutes les classes qui mettent en œuvre IProtocolClient d'avoir connaissance des deux signatures, puis ajouter la signature de surcharge au proxy

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

Si vous voulez masquer cette signa ture dans certaines implémentations, vous pouvez le mettre en œuvre explicitement

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(); 
     }  
} 

Mais si vous avez seulement besoin de la signature étendue dans le cadre de l'une classe par exemple, votre dernier exemple était correct, où classB implémente l'interface originale et ajoute ensuite la signature de surcharge. Dans ce cas, cependant, quiconque publie classB à IProtocolInterface ne verra pas la deuxième signature.

0

Si vous passez tous les paramètres comme un objet, vous pouvez dériver la classe de paramètres et la transtyper dans votre méthode implémentée.

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

Questions connexes