web-dev-qa-db-fra.com

Implémentation de quelques méthodes d'une interface classe-C #

Est-il possible en C # d’avoir une classe qui implémente une interface qui a 10 méthodes déclarées mais qui n’implémente que 5 méthodes, c’est-à-dire qui ne définit que 5 méthodes de cette interface? En fait, j'ai une interface qui est implémentée par 3 classes et toutes les méthodes ne sont pas utilisées par toute la classe alors si je pouvais exclure n'importe quelle méthode ??? 

J'ai besoin de ça. Cela peut sembler une mauvaise conception, mais pas avec espoir. Le problème, c’est que j’ai une collection de contrôles utilisateur qui doit avoir une propriété commune et que, par conséquent, je ne les affiche que lors de l’exécution. Comme c'est dynamique, j'ai besoin de les gérer pour que je reçois des propriétés. Certaines propriétés sont nécessaires à quelques classes et non à toutes. Et au fur et à mesure que le contrôle augmente, il est possible que les propriétés augmentent, ainsi, au besoin, d'un contrôle dont j'ai besoin, sans aucune utilisation. juste les méthodes factices. Pour la même chose, j’ai pensé que s’il existait un moyen d’éviter ces méthodes au reste de la classe, ce serait formidable. Il semble qu'il n'y ait pas d'autre moyen que d'avoir soit la classe abstraite, soit des fonctions factices :-(

24
Jankhana

Vous pouvez en faire une classe abstraite et ajouter les méthodes que vous ne souhaitez pas implémenter en tant que méthodes abstraites.

En d'autres termes:

public interface IMyInterface
{
    void SomeMethod();
    void SomeOtherMethod();
}

public abstract class MyClass : IMyInterface
{
    // Really implementing this
    public void SomeMethod()
    {
        // ...
    }

    // Derived class must implement this
    public abstract void SomeOtherMethod();
}

Si ces classes doivent toutes être concrètes et non abstraites, vous devrez alors jeter une variable NotImplementedException/NotSupportedException à l'intérieur des méthodes. Mais une bien meilleure idée serait de scinder l’interface afin que les classes d’implémentation n’aient pas à le faire.

N'oubliez pas que les classes peuvent implémenter plusieurs interfaces. Par conséquent, si certaines classes possèdent certaines fonctionnalités mais pas toutes, vous souhaitez disposer d'interfaces plus granulaires:

public interface IFoo
{
    void FooMethod();
}

public interface IBar()
{
    void BarMethod();
}

public class SmallClass : IFoo
{
    public void FooMethod() { ... }
}

public class BigClass : IFoo, IBar
{
    public void FooMethod() { ... }
    public void BarMethod() { ... }
}

C'est probablement la conception que vous devriez vraiment avoir.

25
Aaronaught

Votre rupture avec l'utilisation des interfaces. Vous devriez avoir pour chaque comportement commun une interface séparée.

18
RvdK

Bien que je sois d’accord avec @PoweRoy, vous devez probablement diviser votre interface en parties plus petites. Vous pouvez probablement utiliser des interfaces explicites pour fournir une API publique plus propre à vos implémentations d’interface. 

Par exemple:

public interface IPet
{
   void Scratch();
   void Bark();
   void Meow();
}

public class Cat : IPet
{
    public void Scratch()
    {
        Console.WriteLine("Wreck furniture!");
    }

    public void Meow()
    {
       Console.WriteLine("Mew mew mew!");
    }

    void IPet.Bark()
    {
        throw NotSupportedException("Cats don't bark!");
    }
}

public class Dog : IPet
{
    public void Scratch()
    {
        Console.WriteLine("Wreck furniture!");
    }

    void IPet.Meow()
    {
       throw new NotSupportedException("Dogs don't meow!");
    }

    public void Bark()
    {
        Console.WriteLine("Woof! Woof!");
    }
}

Avec les classes définies ci-dessus:

var cat = new Cat();
cat.Scrach();
cat.Meow();
cat.Bark(); // Does not compile


var dog = new Dog();
dog.Scratch();
dog.Bark();
dog.Meow(); // Does not compile.


IPet pet = new Dog();
pet.Scratch();
pet.Bark();
pet.Meow(); // Compiles but throws a NotSupportedException at runtime.

// Note that the following also compiles but will
// throw NotSupportedException at runtime.
((IPet)cat).Bark();
((IPet)dog).Meow();
4
orj

Ce n'est pas possible. Mais ce que vous pouvez faire, c'est lancer NotSupportedException ou NotImplementedException pour les méthodes que vous ne souhaitez pas implémenter. Ou vous pouvez utiliser une classe abstraite au lieu d'une interface. De cette façon, vous pouvez fournir une implémentation par défaut pour les méthodes que vous choisissez de ne pas remplacer.

public interface IMyInterface
{
  void Foo();

  void Bar();
}

public class MyClass : IMyInterface
{
  public void Foo()
  {
    Console.WriteLine("Foo");
  }

  public void Bar()
  {
    throw new NotSupportedException();
  }
}

Ou...

public abstract class MyBaseClass
{
  public virtual void Foo()
  {
    Console.WriteLine("MyBaseClass.Foo");
  }

  public virtual void Bar()
  {
    throw new NotImplementedException();
  }
}

public class MyClass : MyBaseClass
{
  public override void Foo()
  {
    Console.WriteLine("MyClass.Foo");
  }
}
4
Brian Gideon

Vous pouvez simplement avoir les méthodes que vous ne voulez pas implémenter émettent une 'NotImplementedException'. De cette façon, vous pouvez toujours implémenter l'interface normalement.

3
UpTheCreek

Voici un exemple simple et stupide de ce que je voulais dire par différentes interfaces à des fins différentes. Il n'y a pas d'interface pour les propriétés communes car cela compliquerait l'exemple. De plus, ce code manque de beaucoup d'autres choses intéressantes (comme suspendre la mise en page) pour le rendre plus clair. Je n'ai pas essayé de compiler ce code, il y a donc peut-être beaucoup de fautes de frappe, mais j'espère que cette idée est claire.

interface IConfigurableVisibilityControl
{
    //check box that controls whether current control is visible
    CheckBox VisibleCheckBox {get;}
}


class MySuperDuperUserControl : UserControl, IConfigurableVisibilityControl
{
    private readonly CheckBox _visibleCheckBox = new CheckBox();

    public CheckBox VisibleCheckBox 
    {
        get { return _visibleCheckBox; }
    }
    //other important stuff
}

//somewhere else
void BuildSomeUi(Form f, ICollection<UserControl> controls)
{
    //Add "configuration" controls to special panel somewhere on the form
    Panel configurationPanel = new Panel();
    Panel mainPanel = new Panel();
    //do some other lay out stuff
    f.Add(configurationPanel);
    f.Add(mainPanel);

    foreach(UserControl c in controls) 
    {
        //check whether control is configurable
        IConfigurableOptionalControl configurableControl = c as IConfigurableVisibilityControl;
        if(null != configurableControl) 
        {
            CheckBox visibleConfigCB = configurableControl.VisibleCheckBox;
            //do some other lay out stuff
            configurationPanel.Add(visibleConfigCB);
        }
        //do some other lay out stuff
        mainPanel.Add(c);
    }
}
1
SergGr

Non ce n'est pas. Vous devez définir toutes les méthodes de l'interface, mais vous êtes autorisé à les définir en tant qu'abstraits et à laisser l'implémentation à n'importe quelle classe dérivée. Vous ne pouvez pas compiler une classe qui dit qui implémente une interface alors que ce n'est pas le cas.

1
Otávio Décio

Je veux ajouter dynamiquement le contrôle à ma forme car j'ai cela comme exigence. J'ai trouvé le code de ici . Je l'ai édité selon mes besoins. J'ai donc la classe IService qui a les propriétés communes. Ceci est implémenté par les contrôles utilisateur. Qui sont affichés au moment de l'exécution dans différents projets. Hmmm pour cela, j'ai une interface commune différente qui a des propriétés qui sont utilisées par le projet pour afficher les contrôles. Par exemple, peu de contrôles nécessitent des méthodes ou des propriétés supplémentaires pour implémenter un menu contextuel basé sur la sélection de l'utilisateur au moment de l'exécution. C'est-à-dire que les valeurs sont là dans le projet. Elles seront transmises au contrôle et elles seront affichées. Maintenant ce menu n’est là que pour un seul contrôle qui n’a pas cela. J'ai donc pensé qu'il y avait un moyen de ne pas avoir ces méthodes dans toutes les classes plutôt que dans une seule classe. Mais il semble que je doive choisir des méthodes factices ou des classes abstraites. Les méthodes factices hmmm me seraient plus préférables que la classe abstraite :-(

0
Jankhana

Outre les excellentes suggestions ci-dessus sur la conception d'interfaces, si vous avez vraiment besoin d'implémentation de certaines méthodes, vous pouvez également utiliser les «méthodes d'extension». Déplacez les méthodes nécessitant une implémentation en dehors de votre interface. Créez une autre classe statique qui les implémente en tant que méthodes statiques avec le premier paramètre comme "this interfaceObject". Ceci est similaire aux méthodes d'extension utilisées dans LINQ pour l'interface IEnumerable. 

public static class myExtension {
    public static void myMethod( this ImyInterface obj, ... ) { .. }
...
}
0
shr

En implémentant l'un des principes SOLID qui est le "principe de séparation d'interface" dans lequel l'interface est divisée en plusieurs interfaces.

0
hammad

Laissez votre interface être implémentée dans une classe abstraite. La classe abstraite implémentera 5 méthodes et conservera les méthodes restantes en tant que virtuelles. Toutes vos 3 classes doivent alors hériter de la classe abstraite. C'était votre code client qui utilise 3 classes ne devra pas changer.

0