Frage

Ich bin mir nicht sicher, ob dies ist eine seltsame Sache zu tun oder nicht, oder ob es einige, wie Code Geruch ... aber ich frage mich, ob es eine Möglichkeit (eine Art von oop Mustern wäre schön) war „cast“ ein Basistyp zu einer Form seines abgeleiteten Typs. Ich weiß, das macht wenig Sinn, da der abgeleiteten Typ zusätzliche Funktionen haben wird, dass die Eltern nicht bieten, das in seiner Selbst ist nicht grundsätzlich gesund. Aber ist es eine Möglichkeit, dies zu tun? Hier ist ein Codebeispiel, so kann ich besser erklären, was ich "m zu fragen.

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

Ich weiß, das scheint doof aber ist es eine Möglichkeit, etwas von dieser Art zu erreichen?

War es hilfreich?

Lösung

Nicht stichhaltig, in "managed" Sprachen. Dies ist Downcasting , und es gibt keine vernünftige nach unten, wie es zu handhaben, genau dem Grunde, die Sie beschrieben (Subklassen mehr als Basisklassen bieten - was ist diese „mehr“ kommen aus?). Wenn Sie wirklich ein ähnliches Verhalten für eine bestimmte Hierarchie möchten, können Sie Konstruktoren für abgeleitete Typen verwenden, die den Basistyp als Prototyp nehmen.

Man könnte etwas mit Reflexion aufbauen, die die einfachen Fälle (speziellere Typen, die keinen Zusatz Zustand haben) behandelt. In der Regel nur Redesign, das Problem zu vermeiden.

Edit: Woops kann nicht Umwandlung Betreiber zwischen Basis / abgeleiteten Typen schreiben. Eine Kuriosität von Microsoft versuchen, „Sie zu schützen“ gegen sich selbst. Ah gut, zumindest sind sie nicht annähernd so schlimm wie Sonne.

Andere Tipps

Versuchen Zusammensetzung statt Vererbung!

Es scheint mir, wie Sie besser dran wäre eine Instanz von Somebaseclass zum SomeDerivedClass vorbei (was nicht mehr ableiten Basisklasse, und sollten als solche umbenannt werden)

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

Sehen Sie sich http: //www.javaworld. com / Javaworld / jw-11-1998 / jw-11-techniques.html (Seite 3):

  

Wiederverwendung von Code über Zusammensetzung Zusammensetzung   bietet eine alternative Möglichkeit für Apple   Fruit-Implementierung zur Wiederverwendung von   schälen(). Statt Fruit of erstreckt,   Apple kann einen Verweis auf eine Frucht halten   Instanz und definieren einen eigenen Peel ()   Verfahren, die einfach peel aufruft () auf   die Frucht.

Ich persönlich glaube nicht, dass es die Mühe wert Vererbung in diesem Fall der Verwendung. Statt nur die Instanz der Basisklasse übergeben in in den Konstruktor und Zugriff auf sie durch eine Membervariable.

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

einziehe macht Sinn, wenn Sie ein Objekt der abgeleiteten Klasse haben, aber es ist durch einen Verweis von Basisklassentyp und aus irgendeinem Grund Sie wollen es wieder referenziert werden von einer abgeleiteten Klasse Typ Referenz verwiesen wird. Mit anderen Worten: Sie können die niedergeschlagenen den Effekt des vorherigen Upcasting umkehren. Aber Sie können nicht ein Objekt der Basisklasse durch einen Verweis von einem abgeleiteten Klasse Typ verwiesen haben.

Ich sage nicht, dass ich dies empfehlen. Aber man konnte Basisklasse in JSON-String drehen und dann wandeln sie in der abgeleiteten Klasse.

SomeDerivedClass layer = JsonConvert.DeserializeObject<SomeDerivedClass>(JsonConvert.SerializeObject(BaseClassObject));

Nein, das ist nicht möglich. In einer verwalteten Sprache wie C #, es wird einfach nicht funktionieren. Die Laufzeit wird es nicht zulassen, dass, auch wenn der Compiler lässt es durch.

Sie haben selbst gesagt, dass dies scheint doof:

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

Sie sich also fragen, ist class tatsächlich eine Instanz von SomeDerivedClass? Nein, so macht die Umwandlung keinen Sinn. Wenn Sie konvertieren SomeBaseClass müssen SomeDerivedClass, dann sollten Sie eine Art Konvertierung bieten, entweder einen Konstruktor oder ein Umwandlungsverfahren.

Es klingt, als ob Sie Ihre Klassenhierarchie einige Arbeit braucht, though. Im Allgemeinen ist es nicht möglich sein, eine Basisklasse-Instanz in einer abgeleiteten Klasse Instanz zu konvertieren. Es sollte in der Regel Daten und / oder Funktionalität, die auf die Basisklasse nicht gelten. Wenn die abgeleitete Klasse Funktionalität gilt für alle Instanzen der Basisklasse, dann sollte es entweder in die Basisklasse aufgerollt oder in eine neue Klasse gezogen, die nicht Teil der Basisklassenhierarchie ist.

Sprache C # ermöglicht nicht solche Operatoren, aber man kann sie immer noch schreiben, und sie arbeiten:

[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Implicit(Base a) { ... }

[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Explicit(Base a) { ... }

Ja -. Dies ist ein Code Geruch, und so ziemlich Nägel auf der Tatsache, dass Ihre Vererbungskette unterbrochen ist

Mein Vermutung (aus der begrenzten Probe) ist, dass Sie eher DerivedClass auf einer Instanz von Somebaseclass arbeiten haben würden - so, dass "DerivedClass hat einen Somebaseclass", eher als "DerivedClass ist ein Somebaseclass". Dies wird als „für Komposition der Vererbung“ bekannt ist.

Wie andere erwähnt haben, ist das Gießen Sie vorschlagen, nicht wirklich möglich. Wäre es vielleicht ein Fall sein, wenn die Dekorierermuster (Head First-Extrakt) kann eingeführt werden?

Haben Sie sich Gedanken über eine Schnittstelle, die das derzeit Ihre Basisklasse und der abgeleiteten Klasse beide implementieren würde? Ich weiß nicht, die Besonderheiten, warum Sie diese Art und Weise sind die Umsetzung aber es könnte funktionieren.

Dies ist Downcasting und Seldaek Vorschlag als „sichere“ Version ist Ton zu verwenden.

Hier ist ein recht ordentliches Beschreibung mit Code-Beispiele .

Dies ist nicht möglich, da wie wollen Sie die „extra“ erhalten, dass die abgeleitete Klasse hat. Wie würde der Compiler wissen, dass Sie derivedClass1 und nicht derivedClass2 bedeuten, wenn Sie es instanziiert?

Ich denke, was Sie wirklich suchen die Fabrik Muster ist oder ähnlich, so können Sie Objekte instanziiert, ohne wirklich die explizite Art zu wissen, dass instantiate Wesen. In Ihrem Beispiel würde die „Einfügen“ Verfahren mit seinem eine Schnittstelle, die beispielsweise die Fabrik liefert Geräte.

Ich weiß nicht, warum niemand das gesagt hat, und ich kann etwas vermissen, aber Sie das als Schlüsselwort verwenden können, und wenn Sie eine if-Anweisung Verwendung tun müssen, wenn.

SomeDerivedClass derClass = class as SomeDerivedClass; //derClass is null if it isnt SomeDerivedClass
if(class is SomeDerivedClass)
    ;

Ich habe diese Frage schon vor langer Zeit

Ich habe in der Notwendigkeit, vor kurzem mit einem abgeleiteten Typ, um eine einfache DTO der Verlängerung einige weitere Eigenschaften auf sie zu setzen. Ich wollte dann eine Konvertierungslogik wiederzuverwenden ich hatte, aus dem internen Datenbanktyp zu dem DTOs.

So wie ich es gelöst war durch einen leeren Konstruktor auf den DTO-Klassen durchzusetzen, ist es wie folgt aus:

class InternalDbType {
    public string Name { get; set; }
    public DateTime Date { get; set; }
    // Many more properties here...
}

class SimpleDTO {
    public string Name { get; set; }
    // Many more properties here...
}

class ComplexDTO : SimpleDTO {
    public string Date { get; set; }
}

static class InternalDbTypeExtensions {
    public static TDto ToDto<TDto>(this InternalDbType obj) where TDto : SimpleDTO, new() {
        var dto = new TDto {
            Name = obj.Name
        }
    }
}

Ich kann dann die Konvertierungslogik von der einfachen DTO wiederverwenden, wenn sie der Komplex eine Umwandlung. Natürlich werde ich in den Eigenschaften des komplexen Typs auf andere Weise zu füllen, aber mit vielen, vereinfacht viele Eigenschaften des einfachen DTO, das ist wirklich die Dinge meiner Meinung nach.

Das kann nicht funktionieren. schauen Go auf der Hilfeseite durch den Compiler-Fehler verknüpft.

Die beste Lösung ist hier Factory-Methoden zu verwenden.

Wie viele Antworten haben darauf hingewiesen, können Sie nicht niedergeschlagen, die absolut Sinn macht.

Doch in Ihrem Fall SomeDerivedClass hat keine Eigenschaften, die ‚fehlende‘ wird. So könnte man eine Erweiterung Methode wie folgt erstellen:

public static T ToDerived<T>(this SomeBaseClass baseClass) 
    where T:SomeBaseClass, new()
{
    return new T()
    {
        BooleanEvaluator = baseClass.BooleanEvaluator,
        GetBaseClassName = baseClass.GetBaseClassName
    };
}

So Sie nicht werfen, nur das Umwandeln:

SomeBaseClass b = new SomeBaseClass();
SomeDerivedClass c = b.ToDerived<SomeDerivedClass>();

Dies funktioniert nur wirklich, wenn alle Daten in der Basisklasse in Form von lesbaren und beschreibbaren Eigenschaften ist.

C ++ behandelt es einen Konstruktor verwenden. C ++ Typecasting . Es scheint wie ein Versehen zu mir. Viele von Ihnen haben das Thema gebracht, was mit den zusätzlichen Eigenschaften der Prozess machen würde. Ich würde antworten, was macht den Compiler tun, wenn es die abgeleitete Klasse erzeugt, wenn der Programmierer nicht die Eigenschaften nicht gesetzt? Ich habe diese Situation ähnlich wie C ++ behandelt. Ich erstelle einen Konstruktor, der die Basisklasse erfolgt dann manuell die Eigenschaften im Konstruktor festgelegt. Dies ist auf jeden Fall vorzuziehen, eine Variable in der abgeleiteten Klasse zu setzen und das Erbe zu brechen. Ich würde es auch über eine Factory-Methode wählen, weil ich der resultierende Code denken wäre sauberer aussehend.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top