Jump to content
Unity Insider Forum

Mehrere Klassen mit verschiedene Types variablen


MaZy

Recommended Posts

Also es ist schwierig zu erklären was ich vorhabe.

Ich habe eine abstrakte Klasse ClassAbstract. Zwei weitere die sie erben ClassA und ClassB.

ClassAbstract hat ein public abstract object engine { get; protected set; } variable, denn darauf möchte ich später bei ClassA ClassB zugreifen. Nun die Klasse ClassA und ClassB haben verschiedene Types für den engine variable. Sagen wir mal EngineA und EngineB. Die beiden Engines haben verschiedene funktionen und variablen. Beispiel kann der EngineA SetVar(var) machen während EngineB var[var] machen kann. 

Deswegen geht die einfache Benutzung von engine.SetVar oder engine.var[var] nicht.

Nun war die Idee ich mache generic types. Also ClassAbstract<T>.  Damit könnte ich das lösen aber jetzt kommt ein anderes Problem.

Denn ich hab ein Manager, der eigentlich alle ClassAbstract als parameter angenommen hat. Nun das klappt bei ClassAbstract<T> nicht.
So sieht der Constructor aus.

public Manager(ClassAbstract a, params ClassAbstract[] a)

 Jetzt weiß ich nicht weiter, denn mich nervt es jede Klasse selber "engine" variable zu erstellen, weil man manchmal das vergisst.

Alternativ kann ich GetEngine<T> machen und das casten lassen, aber finde ich doof. Ich kann auch den engine nicht private machen (um dann GetEngine zu benutzen), weil ich beim Constructor bei base() nochj nicht neue instance geben kann weil vorher im constructor erst paar Sachen geändert werden muss (bin davon abhängig, da es nicht von mir ist).

Beispiel

EngineA.GlobalSettings.tick = 1;
new EngineA(); 

Sonst hab ich keine Idee mehr.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Was man halt immer machen kann (oder eher: muss), um alle Subklassen einer generischen Superklasse zusammenzufassen, ist, der Superklasse eine nicht-generische Superklasse zu geben.

abstract class ClassBase
{
  // Alle nicht-generischen Definitionen
}

abstract class ClassBase<T> : ClassBase
{
  // Alle Definitionen im Zusammenhang mit T
}

class ClassFoo : ClassBase<Foo> { }

Das Problem ist natürlich, dass du bei der Verwendung dieser Superklasse die vom generischen Typ abhängigen Attribute nicht zur Verfügung hast. Da kannst du auch nicht dran rütteln, weil du sonst ins klassische Problem laufen würdest:

ClassBase thing = new ClassFoo();
thing.engine = someEngine;

C# kann halt nicht feststellen, welcher Basistyp für die Zuweisung valide wäre, da nur der statische Typ (der der Variable) zur Compile Time bekannt ist. Entsprechend kann es dir keine Zusicherung geben, dass nur Objekte eines passenden Typs in deine Methode übergeben werden.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich hab mittlerweile so gemacht, dass engine variable nicht mehr public ist. Hab so angepasst, dass man alles per Funktion machen muss, die man von der Abstrakten Klasse bekommt.

vor 20 Stunden schrieb MaZy:

Denn ich hab ein Manager, der eigentlich alle ClassAbstract als parameter angenommen hat. Nun das klappt bei ClassAbstract<T>.

Ich hatte hier ein Formulierungsfehler. Am Ende des Satzes fehlt ein "nicht" ^^. Hoffe war trotzdem verständlich.

Aber deine Idee kann tatsächlich klappen. An diese Reihenfolge hab ich nicht gedacht. 

So hab es probiert. Also das klappt wunderbar. Muss jetzt nicht mehr engine variable jedes mal definieren. Also mein beispiel sieht so aus (der Code ist provisorisch geändert)

public abstract class ClassAbstract<T> : ClassAbstract
{
    protected T engine;
}
  
public abstract class ClassAbstract
{
    public abstract void Do(string do);

    ...
}
  
public class EngineAHelper : ClassAbstract<EngineA>
{
    public EngineAHelper() 
    {
        engine = new EngineA();
    }

    public override void Do(string do)
    {
        engine.Do(do);
    }
  
    ...
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hm... für diesen Fall sollte auch das hier gehen:

public abstract class ClassAbstract<T> : ClassAbstract where T : new()
{
    protected T engine;
  
    public ClassAbstract()
    {
        engine = new T();
    }
}

Dann musst du die Engine nicht immer per Hand initialisieren. Denke außerdem daran, dass du einen Supertypen für T definieren kannst:

public abstract class ClassAbstract<T> : ClassAbstract where T : EngineAbstract

Lässt sich dann auch mit new() kombinieren.

public abstract class ClassAbstract<T> : ClassAbstract where T : EngineAbstract, new()

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ja das mit new() constraints kenn ich schon. Ich hab das bewusst so gemacht, weil  wie ich oben geschrieben habe immer etwas davor getan werden muss bevor man neuen Object erstellt bzw. auch manchmal haben sie ein oder mehrere Parameter.

z.B. EngineA.Settings.bla = 1 usw. Und dann new EngineA().

Die 3rd party libraries sind halt verschieden aufgebaut.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...