Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

Parameter(typ) von Init-Methode soll in der Unterklasse spezifischer sein
rollerfreak2
myCSharp.de - Member

Avatar #avatar-3271.jpg


Dabei seit:
Beiträge: 916

Themenstarter:

Parameter(typ) von Init-Methode soll in der Unterklasse spezifischer sein

beantworten | zitieren | melden

Hallo zusammen,

ich steh grad ein bisschen auf dem Schlauch. Ich hab eine Basis Klasse die mehrere virtual Methoden hat. Unter anderem eine void Init(object data). Nun erben mehrere Klassen diese Klasse und implementieren natürlich auch die Init Methode. Nun ist aber in den Unterklassen das object genauer spezifizierbar, daher dort sollte nicht object data zugelassen werden, sondern ein spezieller Type.

Kann ich die Init Methode der Basisklasse den Typ "data"(object) generisch angeben, ohne die ganze Basisklasse generisch machen zu müssen? Oder muss die ganze Basisklasse generisch definiert werden und in den unterklassen mit where T ... eingeschränkt werden?


public class Test<T>
{
    public virtual Init(T data)
    {

    }
}
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von rollerfreak2 am .
Again what learned...
private Nachricht | Beiträge des Benutzers
Lector
myCSharp.de - Member



Dabei seit:
Beiträge: 862

beantworten | zitieren | melden

Die Basisklasse muss generisch sein. Die Unterklassen können dann von einem genauer spezifierten Typ davon ableiten:


public class BaseClass<T>
{
    public virtual void Init(T obj)
    {
    }
}

public class MyIntClass : BaseClass<int>
{
    public override void Init(int obj)
    {
        ...
    }
}
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Lector am .
private Nachricht | Beiträge des Benutzers
zero_x
myCSharp.de - Member

Avatar #avatar-2567.gif


Dabei seit:
Beiträge: 1.044
Herkunft: Koblenz

beantworten | zitieren | melden

Hallo rollerfreak2,

was spricht dagegen, die Init-Methode der Basisklasse generisch zu machen? Damit hast du keinen Nachteil, nur Vorteile. In der abgeleiteten Klasse kann man dann mit where einschränken. Ob das direkt mit der Methode geht, weiß ich nicht. Das where kannst du andernfalls direkt an der Klasse angeben.

zero_x
zero_x | myCSharp.de - gemeinsam mehr erreichen

Für längere Zeit inaktiv.
private Nachricht | Beiträge des Benutzers
Uwe81
myCSharp.de - Member



Dabei seit:
Beiträge: 282
Herkunft: Ludwigshafen

beantworten | zitieren | melden

Das führt aber beim Substitutionsprinzip zu Problemen.

Nun gibt es in der Basisklasse Test eine Methode Init(object).

Eine abgeleitete Klasse TestDerived hat Init(Foo).

Nun übergebe ich TestDerived als Test irgendwohin und rufe dort Init(new Bar()) auf, weil bei Test ja Init alles haben kann. Dann knallt es.


Logisch möglich wäre es, den Rückgabetyp zu spezialisieren oder den Parameter zu verallgemeinern. Aber auch das ist in C# (zumnindest bis 3.5) nicht möglich. In Java / c++ geht es.
private Nachricht | Beiträge des Benutzers
rollerfreak2
myCSharp.de - Member

Avatar #avatar-3271.jpg


Dabei seit:
Beiträge: 916

Themenstarter:

beantworten | zitieren | melden

Mir ist klar das es auf die weise funktioniert wie Lector es beschrieben hat. Ich dachte man kann eine Methode einer Klasse generisch machen, ohne die Klasse generisch zu definieren. Weil das in meinem UseCase gereicht hätte. Aber nach genaueren drüber nachdenken ist das eigentlich schon richtig so. Weil die Init Methode initialisiert die Klasse mit einem Bestimmten Typ. Also sollte die Klasse auf den Typ beschränkt sein und damit generisch definiert werden.

Danke für die schnellen Antworten.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von rollerfreak2 am .
Again what learned...
private Nachricht | Beiträge des Benutzers
Spontifixus
myCSharp.de - Member

Avatar #avatar-3052.gif


Dabei seit:
Beiträge: 360
Herkunft: Hannover

beantworten | zitieren | melden

Zitat von rollerfreak2
Ich dachte man kann eine Methode einer Klasse generisch machen, ohne die Klasse generisch zu definieren.

Ja das kannst du auch:

public class MyClass {

    public void Init<T>(T parameter) {
    }

}

Oder war das nicht das was du meintest?
private Nachricht | Beiträge des Benutzers
rollerfreak2
myCSharp.de - Member

Avatar #avatar-3271.jpg


Dabei seit:
Beiträge: 916

Themenstarter:

beantworten | zitieren | melden

Genau die Syntax habe ich gesucht. Jetzt stellt sich also nur noch die Frage was nun besser geeignet ist. Die Klasse selbst hält dieses T nicht, im Init wird das Object nur genommen um einige Services zu laden, es wird nicht gespeichert.

Daher Klasse generisch oder Methode generisch?


public class MyClass1 
{
    public void virtual Init<T>(T parameter) 
    {

    }
}

public class MyClass2 : MyClass1
{
   public override void Init<T>(T data)
   {
        //wie kann ich hier das T einschränken?
   }
}


public override void InitStructure<T>(T data) where T : object
//das geht nicht

public override void InitStructure<int>(int data)
//das geht auch nicht
Again what learned...
private Nachricht | Beiträge des Benutzers
BhaaL
myCSharp.de - Member

Avatar #erP6yAFiewXrJTqrvg6R.jpg


Dabei seit:
Beiträge: 655

beantworten | zitieren | melden

Mal ins blaue gefragt: Wenn jede abgeleitete Klasse ein spezifisches Objekt braucht, warum gibts die Methode dann in der Basisklasse? Du kannst sie dort ja so oder so nicht aufrufen.

Unter der Annahme, dass es gehen würde:

class MyBase { public abstract void Init(object o); }
class MyDerived1 : MyBase { public override void Init(Foo f); }
class MyDerived2 : MyBase { public override void Init(Bar b); }

Was würde deiner Meinung nach passieren, wenn du

MyBase b1 = new MyDerived1(); b1.Init(new Bar());
MyBase b2 = new MyDerived2(); b2.Init(new Foo());
MyBase b3 = new MyDerived1(); b3.Init(new MyDerived2());
machst?

Richtig: MyBase kann nicht auf den Typen einschränken, weil sie logischerweise nicht über die abgeleiteten Klassen bescheid wissen kann/soll.

Einzige Lösung: Nicht abstrakt machen, spezifisch pro Klasse - aufrufen kannst dus ja so oder so nicht typisiert über die Base.
Oder vielleicht ein anderes Design für den Fall wählen.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von BhaaL am .
private Nachricht | Beiträge des Benutzers
rollerfreak2
myCSharp.de - Member

Avatar #avatar-3271.jpg


Dabei seit:
Beiträge: 916

Themenstarter:

beantworten | zitieren | melden

Zitat
Wenn jede abgeleitete Klasse ein spezifisches Objekt braucht, warum gibts die Methode dann in der Basisklasse?

Es dient nur dafür das eine gewisse Structure eingehalten wird. Klar ich könnte auch ein Interface Implementieren für diese Init Methode, oder gar kein Interface und die Init einfach public in jede Klasse schreiben, aber ob das besser ist sein mal da hin gestellt.
Zitat
Was würde deiner Meinung nach passieren, wenn du...

Das würde ja nicht gehen, denn MyDerived1 sollte nur Bar's initialisieren können. Wobei wir wieder beim Thema der generischen Klasse wären, den wenn die Klasse den Typ einschränkt macht das schon wieder Sinn.
Again what learned...
private Nachricht | Beiträge des Benutzers
zommi
myCSharp.de - Member

Avatar #avatar-2617.png


Dabei seit:
Beiträge: 1.361
Herkunft: Berlin

beantworten | zitieren | melden

Hi,

ich finde bei C# Generics und IDictionary gehts um was ganz ähnliches.

Nur haben wir dort nicht:

public class Test<T>
{
    public virtual Init(T data)  {//...}
}
sondern:


interface MyInterface<T> : where T : Typ
{
    void DoSomething(T typ);
}

Aber gleiche Problematik!
Generikas mit unterschiedlichen Typen sind einfach nicht zueinander kompatibel, insbesondere gibt es keinen natürlichen BasisTyp, mit dem das Substitutionsprinzip per default erfüllt wäre.
Lediglich in den seltenen Fällen der Return-Wert-Kovarianz, oder der Parameter-Kontravarianz kann man die wieder hinbiegen. Oder aber man führt künstlich einen zusätzlichen Basistyp ein - dem aber die Generizität und damit die typsichere Methode fehlt.

beste Grüße
zommi
private Nachricht | Beiträge des Benutzers
rollerfreak2
myCSharp.de - Member

Avatar #avatar-3271.jpg


Dabei seit:
Beiträge: 916

Themenstarter:

beantworten | zitieren | melden

Sehr gut zusammen gefasst Zoomi.
Again what learned...
private Nachricht | Beiträge des Benutzers
BhaaL
myCSharp.de - Member

Avatar #erP6yAFiewXrJTqrvg6R.jpg


Dabei seit:
Beiträge: 655

beantworten | zitieren | melden

Zitat von rollerfreak2
Zitat
Was würde deiner Meinung nach passieren, wenn du...

Das würde ja nicht gehen, denn MyDerived1 sollte nur Bar's initialisieren können.
Das wäre aber das Problem, weil mans könnte (MyBase nimmt object, nicht Bar).
Zitat von rollerfreak2
Wobei wir wieder beim Thema der generischen Klasse wären, den wenn die Klasse den Typ einschränkt macht das schon wieder Sinn.
In dem Fall wäre vermutlich das generische Interface (wie von zommi angemerkt) sinnvoll. Andererseits aber auch wieder nicht, weil du aufgrund der Spezialisierung so oder so nicht generalisieren kannst.
private Nachricht | Beiträge des Benutzers
rollerfreak2
myCSharp.de - Member

Avatar #avatar-3271.jpg


Dabei seit:
Beiträge: 916

Themenstarter:

beantworten | zitieren | melden

Jepp, genau so ist es. Allerdings finde ich immer noch das die generische Klasse an der Stelle auch greift.
Again what learned...
private Nachricht | Beiträge des Benutzers