2010-02-22 11 views
7

Grüße. Ich habe die folgende Klasse:C# Klassenvererbung

public class Ship 
{ 
    public enum ValidShips 
    { 
     Minesweeper, 
     Cruiser, 
     Destroyer, 
     Submarine, 
     AircraftCarrier 
    } 

    public enum ShipOrientation 
    { 
     North, 
     East, 
     South, 
     West 
    } 

    public enum ShipStatus 
    { 
     Floating, 
     Destroyed 
    } 

    public ValidShips shipType { get; set; } 

    public ShipUnit[] shipUnit { get; set; } 

    public ShipOrientation shipOrientation { get; set; } 

    public ShipStatus shipStatus { get; set; } 

    public Ship(ValidShips ShipType, int unitLength) 
    { 
     shipStatus = ShipStatus.Floating; 

     shipType = ShipType; 

     shipUnit = new ShipUnit[unitLength]; 

     for (int i = 0; i < unitLength; i++) 
     { 
      shipUnit[i] = new ShipUnit(); 
     } 
    } 
} 

Ich möchte diese Klasse erben wie so:

public class ShipPlacementArray : Ship 
{ 

} 

das macht Sinn.

was ich gerne wissen würde ist, wie entferne ich bestimmte Funktionalität der Basisklasse?

zum Beispiel:

public ShipUnit[] shipUnit { get; set; } // from base class 

ich würde es gerne sein:

public ShipUnit[][] shipUnit { get; set; } // in the derived class 

meine Frage ist, wie ich den Code implementieren, die die Basisklasse verbirgt vollständig shipUnit?

sonst werde ich mit zwei ShipUnit-Implementierung in der abgeleiteten Klasse enden.

danke für Ihre Zeit.

ShipPlacementArray behandelt nur ein Schiff. aber das Array spiegelt die Richtungen wider, in die das Schiff platziert werden kann.

+0

Wow, es sieht so aus, als ob ein Ahole durchgekommen ist und die Antworten aller abgelehnt hat. – AaronLS

Antwort

7

Nach meiner Erfahrung war jedes Mal, wenn ich eine Eigenschaft aus einer Klasse in einer geerbten Klasse entfernen wollte, mein Klassendesign fehlerhaft. Eine Möglichkeit zur Lösung dieses Problems besteht darin, eine neue Basisklasse ohne die ShipUnit-Eigenschaft zu erstellen und diese Basisklasse dann zweimal zu übernehmen, einmal für Ihren konkreten Schiffstyp und einmal für Ihren konkreten ShipPlacementArray-Typ. In beiden Unterklassen können Sie ShipUnit nach Bedarf implementieren.

+0

ja als ich ein Anfänger bin, kann ich noch nicht komplett ausdenken. Ich denke, Ihre Informationen lösen das Problem, das ich habe. Teilen Sie die Daten einfach in nützliche Einheiten auf. was ich in gewissem Maße getan habe, aber Ihre Eingabe hat den nächsten Schritt im Design für mich geklärt. Vielen Dank. – iTEgg

+0

@ikurtz - Vererbung sollte immer einer "ist a" -Beziehung folgen. Kannst du sagen "Ein ShipPlacementArray ist ein Schiff" und macht es Sinn (in der Art wie "ein Kreis eine Form hat")? Wenn nicht, dann ist es wieder auf dem Zeichenbrett :) – Paolo

0

können Sie den "neuen" Operator verwenden. wie in

public new ShipUnit[][] shipUnit { get; set; } // in the derived class 
+1

Ich habe abgelehnt, weil neu ist eine Möglichkeit, die Basisklasse-Implementierung zu verbergen und eine neue Vererbungshierarchie zu starten, aber diese Lösung löst das vorgestellte Problem nicht wirklich - es behebt bestenfalls einige Symptome. –

2

Sie können nicht Mitglieder einer Basisklasse machen in einer abgeleiteten Klasse verschwinden. In bestimmten Fällen können Sie oder verstecken die Basiselemente maskieren, indem das new Stichwort auf Ihrem Versteck Mitglied in der abgeleiteten Klasse verwenden, aber der Benutzer immer in der Lage sein, Ihr Objekt zurück auf die Basisklasse (base)instance_of_derived und Zugang zu werfen die Mitglieder der Basisklasse.

So zum Beispiel können Sie in der abgeleiteten Klasse tun:

public new ShipUnit[][] shipUnit { get; set; } 

Aber dann kann ich:

((Ship)ShipPlacementArray_instance).shipUnit 

Und das wird die ursprüngliche shipUnit verweisen. So können Sie das Mitglied "verstecken", aber Sie können seine Funktionalität oder Zugänglichkeit nicht deaktivieren.

15

was ich gerne wissen würde ist, wie entferne ich bestimmte Funktionen der Basisklasse?

Sie nicht. Dies ist nicht der Punkt der Vererbung. Der Vererbungspunkt besteht darin, die Basisklassenfunktionalität zu übernehmen - alle davon - und Dinge hinzuzufügen/zu ändern. Es ist für "ist-a" Beziehungen, z. B. "ein Auto ist ein Fahrzeug."

Meine Frage ist, wie implementiere ich den Code, der die Basisklasse shipUnit vollständig verbirgt?ein Wrapper oder Behälter sein, von mehreren Ship Objekte

Es klingt wie Sie ShipPlacementArray wollen. Dies scheint kein Fall zu sein, in dem Vererbung verwendet werden sollte.

Stellen Sie sich die Frage: "Ist eine ShipPlacementArray eine Art Ship?"

+0

ShipPlacementArray ist kein Schiff, aber es teilt viele Daten/Ähnlichkeiten mit der Schiffsklasse. Deshalb denke ich daran, von der Schiffsklasse zu erben. – iTEgg

+0

In diesem Fall könnten Sie * eine Klasse erstellen, die die allgemeine Funktionalität implementiert, und daraus sowohl "Ship" als auch "ShipPlacementArray" ableiten. Aber wenn Sie wirklich ein Battleship-Spiel erstellen (wie es aus Ihrem Code hervorgeht), kann ich mir nichts Lohnenswertes vorstellen, das die beiden gemeinsam haben. – Thomas

+0

Thomas: Ich habe den ersten Teil von dem verstanden, was du gesagt hast, aber der spätere bin mir nicht sicher, ob ich es verstehe. ShipPlacementArray ist ein Container für einen verfügbaren Schiffsplatzierungsort, wenn das Schiff einem Ort im Gitter zugewiesen wird. – iTEgg

0

Sie können das new Schlüsselwort, wie folgt aus:

public new ShipUnit[][] shipUnit { get; set; } 
+0

Ich habe abgelehnt, weil neu eine Möglichkeit ist, die Basisklassenimplementierung zu verbergen und eine neue Vererbungshierarchie zu starten, aber diese Lösung löst das vorgestellte Problem nicht wirklich - sie behebt bestenfalls einige Symptome. –

+1

@Daniel Brückner Die Frage ist "meine Frage ist, wie implementiere ich den Code, der die Basisklasse shipUnit vollständig verbirgt?", Nicht "wie repariere ich diesen Entwurf?". –

+0

Ja und nein. Es beantwortet die Frage, die der Eröffner stellte, aber es gibt ihm nicht die Informationen, die er (wirklich) braucht. –

2

Mit C# 's neue Modifikator Sie eine geerbte Mitglied von einer Basisklasse Mitglied verstecken können. Check out this Seite als Referenz.

0

Ich verstehe nicht ganz, was Sie mit der Vererbung modellieren wollen, aber ich bin mir ziemlich sicher, dass es das falsche Werkzeug ist. Ich nehme an, aggregation or composition sind was du brauchst.

1

Zusätzlich zu den anderen ausgezeichneten Antworten, als eine Seite würde ich sagen, dass Sie Kapselung als eine bessere Option finden können. Oft dachte ich zuerst, dass ich von einer Klasse erben wollte, und stellte später fest, dass ich es wirklich einkapseln wollte. Sie tun dies, indem Sie einfach eine neue Instanz der ursprünglichen Klasse in einem privaten Feld deklarieren. Sie erstellen dann öffentliche Eigenschaften und Funktionen, die einfach die ursprüngliche Klasse wie die folgende aufrufen, und geben Ihnen damit eine feine Kontrolle darüber, was ausgesetzt wird. Dies ist auch eine Art und Weise zur Seite, die Nachteile der Vererbung wie zusätzliche Komplexität Schritt und die Unfähigkeit, mehrere inheritence auszuführen (aus gutem Grund):

class SomeNew 
{ 
    private SomeOld someOld = new SomeOld();//could have done this in constructor instead 

    public DoSomething() 
    { 
    someOld.DoSomething(); 
    } 
} 
1

Ich weiß nicht, ob dies nur ein konstruiertes Beispiel ist, oder ein tatsächliches Problem. Aber ich würde sagen, dass die Erbschaft in diesem Fall nicht erwünscht ist. Sie haben Ship und ShipPlacementArray. Das "Array" am Ende klingt eher nach seinem Array-Datentyp. Also, wenn du das wegnimmst, hast du ShipPlacement.

Das klingt für mich wie ein Ort irgendwo, also sollte es vielleicht ein Mitglied der Schiffsklasse sein?

1

"Favor Objektkomposition über Klassenvererbung" - Wenn Sie nach einem neuen Verhalten aus der Basisklasse suchen, dann scheint es nicht so, als ob Sie es trotzdem übernehmen möchten, da sie unterschiedliche Typen sind. Vielleicht sollten Ship und ShipPlacementArray eine gemeinsame Schnittstelle erben, aber sicher nicht von einer gemeinsamen Basisklasse. Überall, wo Sie es verwenden müssten, könnten Sie die Schnittstelle verwenden - aber wo Sie Ihre ShipUnit-Matrix benötigen, würden Sie den ShipPlacementArray-Typ explizit verwenden.

0

Sie können das neue Schlüsselwort verwenden oder virtuell in der Deklaration für die Basisklasse hinzufügen und es für die abgeleitete Klasse überschreiben.

Verwandte Themen