253 votes

Héritage multiple en c#

Depuis l'héritage multiple est mauvais (il est la source de plus compliqué) C# ne pas fournir un tel motif directement. Mais parfois, il serait utile d'avoir cette capacité.

Par exemple, je suis capable de mettre en œuvre le manque de l'héritage multiple motif à l'aide d'interfaces et de trois classes comme ça:

public interface IFirst { void FirstMethod(); }
public interface ISecond { void SecondMethod(); }

public class First:IFirst 
{ 
    public void FirstMethod() { Console.WriteLine("First"); } 
}

public class Second:ISecond 
{ 
    public void SecondMethod() { Console.WriteLine("Second"); } 
}

public class FirstAndSecond: IFirst, ISecond
{
    First first = new First();
    Second second = new Second();
    public void FirstMethod() { first.FirstMethod(); }
    public void SecondMethod() { second.SecondMethod(); }
}

Chaque fois que je ajouter une méthode à l'une des interfaces j'ai besoin de changer la classe FirstAndSecond .

Est-il possible d'injecter plusieurs classes existantes dans une nouvelle classe, comme il est possible en C++?

Peut-être il ya une solution à l'aide d'une sorte de génération de code?

Ou il peut ressembler à ceci (imaginaire syntaxe c#):

public class FirstAndSecond: IFirst from First, ISecond from Second
{ }

De sorte qu'il n'y a pas besoin de mettre à jour la classe FirstAndSecond quand je modifie une de ces interfaces.


MODIFIER

Il serait peut-être préférable de considérer un exemple pratique:

Vous avez une classe existante (par exemple, un texte basé sur TCP client sur la base d'ITextTcpClient) que vous utilisez déjà à différents endroits à l'intérieur de votre projet. Maintenant, vous vous sentez le besoin de créer un composant de votre classe afin d'être facilement accessible pour les développeurs windows forms.

Comme je sais que vous avez actuellement deux façons de le faire:

  1. Écrire une nouvelle classe qui est héritée de composants et implémente l'interface de la TextTcpClient classe à l'aide d'une instance de la classe elle-même comme le montre avec FirstAndSecond.

  2. Écrire une nouvelle classe qui hérite de TextTcpClient et en quelque sorte, met en œuvre IComponent (n'ai même pas essayé encore).

Dans les deux cas, vous devez faire le travail par méthode et non par classe. Puisque vous savez que nous aurons besoin de toutes les méthodes de TextTcpClient et Composant ce serait la solution la plus simple à combinez ces deux dans une classe.

Pour éviter les conflits, ce qui peut être fait par la génération de code où le résultat pourrait être modifiée par la suite, mais de taper à la main est une pure douleur dans le cul.

238voto

C. Lawrence Wenham Points 11271

D'examiner à l'aide de la composition , au lieu d'essayer de simuler l'Héritage Multiple. Vous pouvez utiliser les Interfaces pour définir les classes d'inventer la composition, par exemple: ISteerable implique une propriété de type SteeringWheel, IBrakable implique une propriété de type BrakePedal, etc.

Une fois que vous avez fait cela, vous pouvez utiliser les Méthodes d'Extension de fonctionnalité ajoutée de C# 3.0, pour simplifier l'appel de méthodes sur celles implicite les propriétés, par exemple:

public interface ISteerable { SteeringWheel wheel { get; set; } }

public interface IBrakable { BrakePedal brake { get; set; } }

public class Vehicle : ISteerable, IBrakable
{
    public SteeringWheel wheel { get; set; }

    public BrakePedal brake { get; set; }

    public Vehicle() { wheel = new SteeringWheel(); brake = new BrakePedal(); }
}

public static class SteeringExtensions
{
    public static void SteerLeft(this ISteerable vehicle)
    {
        vehicle.wheel.SteerLeft();
    }
}

public static class BrakeExtensions
{
    public static void Stop(this IBrakable vehicle)
    {
        vehicle.brake.ApplyUntilStop();
    }
}


public class Main
{
    Vehicle myCar = new Vehicle();

    public void main()
    {
        myCar.SteerLeft();
        myCar.Stop();
    }
}

151voto

IanNorton Points 3797

Depuis l'héritage multiple est mauvais (il est la source de plus compliqué) C# ne pas fournir un tel motif directement. Mais parfois, il serait utile d'avoir cette capacité.

C# et de la .net CLR n'ont pas mis en œuvre MI parce qu'ils n'ont pas conclu de la façon dont il serait l'interopérabilité entre C#, VB.net et les autres langues encore, non pas parce que "il serait la source au plus complexe"

MI est un concept utile, l'onu, répondu à des questions comme:- "Que voulez-vous faire lorsque vous avez plusieurs communes des classes de base dans les différents super-classes?

Perl est la seule langue que je n'ai jamais travaillé avec où MI fonctionne et fonctionne bien. .Net pourrait bien introduire un jour, mais pas encore, le CLR supporte déjà MI mais comme je l'ai dit, il n'y a pas de constructions de langage pour elle au-delà encore.

Jusqu'alors, vous êtes coincé avec Proxy objets et des Interfaces multiples :(

20voto

Jordão Points 29221

J’ai créé un post compilateur c# qui permet ce genre de chose :

Vous pouvez exécuter le compilateur post comme un post-build-event Visual Studio :

C:\some_path\nroles-v0.1.0-bin\nutate.exe « $(TargetPath) »

Dans le même assembly vous l’utiliser comme ceci :

Dans un autre assembly vous l’utiliser comme ceci :

13voto

Jon Skeet Points 692016

J'aimerais que ce trop - c'est ce que j'ai personnellement se référer à un mélange, bien que je réalise que c'est une surcharge du terme. Je voudrais être en mesure de spécifier la variable utilisée pour implémenter l'interface, avec la possibilité de fournir ma propre mise en œuvre de méthodes spécifiques.

J'ai blogué à ce sujet dans plus de détails - bien que dans le contexte d'une surévaluation délibérée de ce que cela pourrait signifier en termes d'héritage.

Je ne vois pas pourquoi ce ne pouvait pas être mis en œuvre dans le compilateur C# - mais c'est un autre morceau de la complexité du langage...

6voto

Joel Coehoorn Points 190579

Vous pourriez avoir un résumé de la classe de base qui implémente IFirst et ISecond et puis héritent de seulement sur cette base.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X