45 votes

Une manière de convertir un type de base en un type dérivé

Je ne suis pas sûr si c'est une chose étrange à faire ou pas, ou si c'est d'une façon odeur de code...mais je me demandais si il y avait un moyen (une sorte de oop modèle serait bien) à "jeter" un type de base à une forme de son type dérivé. Je sais que cela fait peu de sens comme le type dérivé aura des fonctionnalités supplémentaires que le parent n'est pas l'offre qui est dans son auto n'est pas fondamentalement saine. Mais est-il possible de faire cela? Voici un exemple de code afin que je puisse mieux vous expliquer ce que je"m demandé.

public class SomeBaseClass {
    public string GetBaseClassName {get;set;}
    public bool BooleanEvaluator {get;set;}
}

public class SomeDerivedClass : SomeBaseClass {
    public void Insert(SqlConnection connection) {
          //...random connection stuff
          cmd.Parameters["IsItTrue"].Value = this.BooleanEvalutar;
          //...
    }
}

public static void Main(object[] args) {
    SomeBaseClass baseClass = new SomeBaseClass();
    SomeDerivedClass derClass = (SomeDerivedClass)baseClass; 
    derClass.Insert(new sqlConnection());
}

Je sais que cela peut sembler maladroit, mais est-il possible d'accomplir quelque chose de ce genre?

31voto

Adam Wright Points 31715

Pas à poings fermés, dans "gérer" les langues. C'est de passer, et il n'est pas sain d'esprit vers le bas façon de le gérer, exactement pour la raison que vous avez décrit (sous-classes de fournir plus que des classes de base - où est-ce que "plus" vient?). Si vous voulez vraiment un comportement similaire à une hiérarchie particulière, vous pouvez utiliser les constructeurs de types dérivés, qui va prendre le type de base comme un prototype.

On pouvait construire quelque chose avec la réflexion qui a traité les cas simples (plusieurs types spécifiques qui n'ont pas plus d'état). En général, tout refonte pour éviter le problème.

Edit: Oups, ne peut pas écrire des opérateurs de conversion entre la base/les types dérivés. Une bizarrerie de Microsoft essayant de "protégez-vous" à l'encontre de vous-même. Ah bien, au moins ils sont pas loin d'être aussi mauvais que le Soleil.

18voto

Rob Fonseca-Ensor Points 11697

Essayez de composition à la place de l'héritage!

Il me semble que vous feriez mieux de passer une instance de SomeBaseClass à la SomeDerivedClass (qui n'est plus dériver de la classe de base, et devrait être renommé en tant que tel)

public class BooleanHolder{       
    public bool BooleanEvaluator {get;set;}
}

public class DatabaseInserter{
    BooleanHolder holder;

    public DatabaseInserter(BooleanHolder holder){
        this.holder = holder;
    }

    public void Insert(SqlConnection connection) {
          ...random connection stuff
          cmd.Parameters["IsItTrue"].Value = holder.BooleanEvalutar;
          ...
    }
}

public static void Main(object[] args) {
    BooleanHolder h = new BooleanHolder();
    DatabaseInserter derClass = new DatabaseInserter(h);
    derClass.Insert(new sqlConnection);
}

Découvrez http://www.javaworld.com/javaworld/jw-11-1998/jw-11-techniques.html (page 3):

La réutilisation de Code via la composition de la Composition offre une voie alternative pour Apple pour réutiliser les Fruits de la mise en œuvre de peel(). Au lieu de prolonger les Fruits,les Apple peut contenir une référence à un Fruit instance et de définir ses propres peel() méthode qui appelle simplement peel() sur le Fruit.

15voto

Rob Sedgwick Points 469

Personnellement, je ne pense pas que cela vaille la peine d'utiliser l'héritage dans ce cas. Au lieu de cela, passez simplement l'instance de la classe de base dans le constructeur et accédez-y via une variable membre.

    private class ExtendedClass //: BaseClass - like to inherit but can't
    {
        public readonly BaseClass bc = null;
        public ExtendedClass(BaseClass b)
        {
            this.bc = b;
        }

       public int ExtendedProperty
        {
            get
            {
            }
        }
     }
 

9voto

Maciej Hehl Points 4760

Le downcasting est logique si vous avez un objet de classe dérivée mais qu'il est référencé par une référence de type classe de base et pour une raison quelconque. Vous souhaitez qu'il soit de nouveau référencé par une référence de type de classe dérivée. En d'autres termes, vous pouvez downcast pour inverser l'effet de la conversion en amont précédente. Mais vous ne pouvez pas avoir un objet de classe de base référencé par une référence de type classe dérivée.

5voto

Derek Park Points 25025

Non, ce n'est pas possible. Dans une langue comme le C#, il juste ne fonctionnera pas. Le moteur d'exécution ne permettent pas, même si le compilateur permet de à travers.

Vous l'avez dit vous-même que cela semble maladroit:

SomeBaseClass class = new SomeBaseClass();
SomeDerivedClass derClass = (SomeDerivedClass)class;

Alors demandez-vous, est - class en fait une instance d' SomeDerivedClass? Non, la conversion n'a pas de sens. Si vous avez besoin de convertir SomeBaseClass de SomeDerivedClass, alors vous devez fournir une sorte de conversion, un constructeur ou une méthode de conversion.

Il semble que votre hiérarchie de classe a besoin de quelques travaux, mais. En général, il ne devrait pas être possible de convertir une instance de la classe de base dans une classe dérivée de l'instance. Il ne devrait généralement être données et/ou des fonctionnalités qui ne s'appliquent pas à la classe de base. Si la classe dérivée fonctionnalité s'applique à toutes les instances de la classe de base, alors il devrait être roulé dans la classe de base ou tiré dans une nouvelle classe qui ne fait pas partie de la classe de base de la hiérarchie.

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