Vererbung + Interface

  • VB.NET
  • .NET 7–8

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Vererbung + Interface

    Hallo,

    wenn ich von einer Basisklasse erbe, die ein Interface implementiert, dann verliert eine abgeleitete Klasse die Restriktionen des Interfaces, wenn jene nicht MustOverride sind.
    Dazu muss die Basisklasse aber MustInherit sein.
    Wenn ich aber sowohl die abgeleitete Klasse als auch die Basisklasse nutzen möchte (das MustInherit also stört), bei denen Restriktionen eines Interfaces gelten, wie müsste man das realisieren?

    Viele Grüße

    Haudruferzappeltnoch schrieb:

    wenn ich von einer Basisklasse erbe, die ein Interface implementiert, dann verliert eine abgeleitete Klasse die Restriktionen des Interfaces, wenn jene nicht MustOverride sind.


    Inwieweit?

    VB.NET-Quellcode

    1. Friend Interface IFoo
    2. Property ColorIndex As Integer
    3. End Interface
    4. Friend Class Bar : Implements IFoo
    5. Property ColorIndex As Integer Implements IFoo.ColorIndex
    6. End Class
    7. Friend Class Baz : Inherits Bar : End Class
    8. Sub Main()
    9. Dim Baz As New Baz
    10. Baz.ColorIndex = 1
    11. Method(Baz)
    12. End Sub
    13. Private Sub Method(AnyFoo As IFoo)
    14. AnyFoo.ColorIndex = 1
    15. End Sub

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @Haudruferzappeltnoch

    Nein, so wirklich geht das nicht.

    Bar und Baz haben, trotz dass sie von Foo erben, dennoch unterschiedliche Attribute und Methoden.

    Wenn Foo die Funktionalität bietet, die du benötigst, dann kannst du immer auf den gemeinsamen Nenner herunterbrechen.
    Vertikales Morphen funktioniert immer, horizontal eher schwierig und wenn dann auch nur mit biegen und brechen. In der C++-Welt wäre das z.B. undefiniertes Verhalten.

    C-Quellcode

    1. class Foo {
    2. public:
    3. virtual void foo1() = 0; // Pure-virtual
    4. };
    5. class Bar: public Foo {
    6. public:
    7. virtual void foo1() { /* do something */ }
    8. void bar1() const { /* do something else */ }
    9. };
    10. public Baz: public Foo {
    11. public:
    12. virtual void foo1() { /* do something slightly differently */ }
    13. void baz1() const { /* something entirely different */ }
    14. }
    15. int main() {
    16. Foo* myFoo{nullptr};
    17. myFoo = new Foo(); // Funktioniert nicht, Foo ist eine abstrakte Klasse
    18. myFoo = new Bar(); // Funktioniert, vertikale gemorpht
    19. myFoo = new Baz(); // Geht auch
    20. Bar* myBar = new bar(); // Funktioniert
    21. myBar = new Baz(); // Funktioniert nicht, weil Baz noch die Funktion baz1 enthält.
    22. // Really dirty
    23. Baz* myBaz = reinterpret_cast<Baz>(new Bar()); // Funktioniert, ist aber undefiniertes Verhalten und wird oft auch von Compilern gewarnt.
    24. myBaz->baz1(); // Zugriff auf ungültigen Speicher
    25. myBaz->bar1(); // Wird vom Compiler nicht gefunden, also Compilerwarnung
    26. return 0;
    27. }
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.
    Ok, aber wenn ich Foo in Bar verwandle warum kann Foo dann plötzlich bar1 oder baz1?
    In meinem Fall ist es eher so:

    VB.NET-Quellcode

    1. Public Class Foo
    2. Public Sub New(iwas)
    3. ...
    4. End Sub
    5. End Class
    6. Public Class Bar
    7. Inherits Foo
    8. Public Sub New(iwas)
    9. MyBase.New(iwas)
    10. End Sub
    11. End Class
    12. Public Class Baz
    13. Inherits Foo
    14. Public Sub New(iwas)
    15. MyBase.New(iwas)
    16. End Sub
    17. Public ReadOnly Property beliebig as Boolean
    18. Get
    19. Return True
    20. End Get
    21. End Property
    22. End Class


    Also Foo1 = New Foo: DirectCast(Foo1, Baz) kennt plötzlich beliebig
    Aber Bar kann es nicht, obwohl Bar nicht weniger drauf hat als Foo.
    Ich schätze nur ein Problem für den Compiler nicht für die Klassen?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Stop. Nur, weil der Compiler zur Designzeit nicht meckert, heißt das nix:

    Und von Bar zu Foo nach Baz geht logisch daher auch nicht. Wäre wie: von Hund zu Tier zu Meerschwein.

    Also: der Compiler kann eine abgeleitete Klasse wie einer ihrer Basisklassen behandeln. Aber eine Klasse kann nicht wie eine abgeleitete Klasse davon behandelt werden, wenn die Instanz nicht tatsächlich vom abgeleiteten Typ ist. Stichwort Upcasting und Downcasting.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    Wie @VaporiZed bereits gesagt hat, nein.

    Was du machen kannst, ist eine "Grundmethode" einbauen.

    In meinem Beispiel oben siehst du, dass foo() in allen Klassen vorhanden ist, aber in Foo als "abstrakt" (pure virtual) markiert ist.
    Jede erbende Klasse muss foo() enthalten. Was genau foo() dann am Ende des Tages macht, ist egal.

    Du kannst also immer sagen:

    C-Quellcode

    1. Foo* foo = new Bar();
    2. foo->foo(); // Macht aber bar(), weil in foo() so definiert.
    3. delete foo;
    4. foo = new Baz();
    5. foo->foo(); // Macht jetzt baz()
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.

    Haudruferzappeltnoch schrieb:

    Ok, aber wenn ich Foo in Bar verwandle warum kann Foo dann plötzlich bar1 oder baz1?
    mehrere Denkfehler.
    • du kannst Foo nicht in Bar verwandeln
      Weil Foo, Bar Baz sind Datentypen, die können garnix. Man kann allerdings Objekte des jeweiligen Datentyps bauen.
    • Du kannst dem Compiler mitteilen, dass er ein bestimmtes Foo-Objekt wie ein Bar behandeln kann.
      Die Verantwortung liegt dann bei dir: Ist das Foo-Objekt in Wirklichkeit gar kein Bar, sondern ist es ein Foo, oder ein Baz, so kommt die InvalidCast-Exception.
      Das hat mit "verwandeln" nichts zu tun. Wenn ich dir sage: "Dieses Tier-Objekt ist ein Hund" - dann ist das Tier dadurch ja nicht verwandelt.
      Aber du weisst dann, dass du damit Gassi gehen kannst.
      Habe ich dir falsch Information gegeben, kommts beim Gassigehen aber zum Fehler.