it-swarm.com.de

Was ist ein gutes Beispiel für Klassenvererbung?

Ich schreibe Dokumentation für eine objektorientierte Sprache, und ich frage mich, welche Art von Klassen ein gutes Beispiel für Vererbung wäre.

Einige häufige Beispiele:

class Person {
}
class Employee extends Person {
}

Momentan mein Favorit, aber ich mag Person-> Employee nicht, weil 'Employee' nicht gerade nach Spaß aussieht.

class Bicycle {
}
class MountainBike extends Bicycle {
}

Ich habe dies in einem Java-Tutorial gefunden, aber es ist nicht wirklich offensichtlich, welche Eigenschaften ein Fahrrad haben sollte.

class Animal {
}
class Bird extends Animal {
}

Gleich wie das Fahrrad.

class A {
}
class B extends A {
}

Zu abstrakt Das Hauptproblem ist, dass eine solche Klasse noch abstraktere Attribute und Methoden benötigt.

Hat jemand ein besseres Beispiel für eine einfache Klassenhierarchie?

26
Tim Jansen

Ich mag die Hierarchie Stream. Die Idee ist, dass alles einen Stream verwenden kann, ohne sich zu kümmern, um welche Art von Stream es sich handelt, und einzelne Unterklassen behandeln den Speicher unterschiedlich (z. B. NetworkStream, MemoryStream und FileStream in .NET).

Wenn Sie an Schnittstellen interessiert sind, ist IEnumerable<T> in .NET eine großartige Sache - Sie können jede Auflistung durchlaufen, ohne sich um die zugrunde liegende Datenstruktur zu kümmern.

18
Jon Skeet

Autoteile können beispielsweise interessant sein

class part
{
    OEM
    Manufacturer
    Number
    Description
}

class Tire extends Part
{
   Speed
   Rating

}
17
JoshBerke

Ich stimme Jon Skeet hinsichtlich seines Stream-Beispiels zu. Vielleicht ist es nicht perfekt, aber es hat einen Vorteil gegenüber den meisten Beispielen:

Es ist realistisch

Fahrräder, Personen oder Tiere, Formen oder Waffen würden in realen Projekten nicht durch Vererbung modelliert. (insbesondere formen sind geradezu gefährlich, weil es funktioniert nicht .)

Das ist mein Liebling mit Erbschaft. Es wird zu oft als etwas gelehrt, das muss verwendet werden, um jede Hierarchie auszudrücken, die Sie finden können. Ein Angestellter ist eine Person, richtig? Also die Employee-Klasse muss von einer Person-Klasse erben. Aber eine Person ist auch eine LivingCreature, also sollten wir auch eine dieser Klassen haben. Und ein LivingCreature ist auch ein Organismus, also haben wir eine andere Klasse. Und ein Organismus ist ... Fühlen Sie sich frei, um fortzufahren.

Ich denke, es wäre schön, wenn irgendjemand tatsächlich Vererbung lehrte, indem er erklärte, wann es verwendet werden sollte, und nicht nur, wie man es über jede Hierarchie herunterschalten kann, ob es von Vorteil ist oder nicht.

Streams (oder Geräte wie in ChrisWs Beispiel) haben den Vorteil, dass sie Sinn machen. Sie möchten in der Lage sein, alle Streams gleich zu behandeln, unabhängig davon, ob sie mit einem Speicherpuffer, einer Datei oder einem Netzwerksockel verbunden sind. Und alle Hardwaregeräte haben eine Menge gemeinsames Verhalten, das plausibel in eine Device-Basisklasse umgerechnet werden könnte.

17
jalf

Viele Leute verwenden das Shapes-Beispiel, aber das ist in der Tat gefährlich. Das Problem entsteht, wenn Sie intuitiv entscheiden, dass ein Quadrat eine Unterklasse eines Rechtecks ​​ist. 

In Bezug auf das Verhalten ist ein Quadrat mehr als ein Rechteck, wodurch die Substituierbarkeit gebrochen wird. Zum Beispiel könnten wir ein Rechteckobjekt bitten, seine Höhe zu ändern. Wenn ein Quadrat eine Unterklasse eines Rechtecks ​​ist, bedeutet dies, dass wir in der Lage sein sollten, dasselbe nach einem Quadrat zu fragen. Wenn Sie die Höhe eines Quadrats ändern, bedeutet dies, dass es nicht mehr ein Quadrat ist. Natürlich könnten wir die Breite entsprechend vergrößern, aber das ist nicht das, was wir erwarten würden, wenn wir ein Objekt mit deklariertem Typrechteck, das eigentlich ein Quadrat ist, dazu auffordert, seine Höhe zu ändern.

Es wird das Liskov-Substitutionsprinzip genannt , und Sie sollten es bei jeder ernsthaften OO Entwicklung beachten. 

Quadrate sind natürlich ein subset von Rechtecken anstelle eines subclass. Dies ist der Unterschied zwischen datenorientierten und verhaltensorientierten Ansätzen.

Wie Jon ziehe ich Streams als Beispiel vor. Es ist nicht schwer zu erklären, auch für Nicht-Programmierer, und es ist klar verhaltensorientiert, so dass die Konturenuniversität der Formen vermieden wird.

8
Rik

Wenn Sie sich für Videospiele interessieren, könnte dies so aussehen:

class enemy{
  Health
  Posx
  posy
  Etc
}

class orc : extends enemy{
 speed
 Strength
 etc
}
8
luis

Was ist mit einer Hierarchie algebraischer Ausdrücke? Dies ist ein hervorragendes Beispiel, da sowohl Vererbung als auch Komposition verwendet werden:

public interface Expression {
    int evaluate();

    public class Constant implements Expression {

        private final int value;

        public Constant(int value) {
            this.value = value;
        }

        @Override
        public int evaluate() {
            return this.value;
        }

        @Override
        public String toString() {
            return String.format(" %d ", this.value);
        }

    }

    public class Negate implements Expression {

        private final Expression expression;

        public Negate(Expression expression) {
            this.expression = expression;
        }

        @Override
        public int evaluate() {
            return -(this.expression.evaluate());
        }

        @Override
        public String toString() {
            return String.format(" -%s ", this.expression);
        }
    }

    public class Exponent implements Expression {

        private final Expression expression;
        private final int exponent;

        public Exponent(Expression expression, int exponent) {
            this.expression = expression;
            this.exponent = exponent;
        }

        @Override
        public int evaluate() {
            return (int) Math.pow(this.expression.evaluate(), this.exponent);
        }

        @Override
        public String toString() {
            return String.format(" %s ^ %d", this.expression, this.exponent);
        }

    }

    public class Addition implements Expression {

        private final Expression left;
        private final Expression right;

        public Addition(Expression left, Expression right) {
            this.left = left;
            this.right = right;
        }

        @Override
        public int evaluate() {
            return this.left.evaluate() + this.right.evaluate();
        }

        @Override
        public String toString() {
            return String.format(" (%s + %s) ", this.left, this.right);
        }
    }

    public class Multiplication implements Expression {

        private final Expression left;
        private final Expression right;

        public Multiplication(Expression left, Expression right) {
            this.left = left;
            this.right = right;
        }

        @Override
        public int evaluate() {
            return this.left.evaluate() *  this.right.evaluate();
        }

        @Override
        public String toString() {
            return String.format(" (%s * %s) ", this.left, this.right);
        }
    }

}

Dann können Sie ein motivierendes Beispiel geben:

public static void main(String[] args) {

    Expression two = new Constant(2);
    Expression four = new Constant(4);
    Expression negOne = new Negate(new Constant(1));
    Expression sumTwoFour = new Addition(two, four);
    Expression mult = new Multiplication(sumTwoFour, negOne);
    Expression exp = new Exponent(mult, 2);
    Expression res = new Addition(exp, new Constant(1));

    System.out.println(res + " = " + res.evaluate());

}

Was würde ergeben:

(  ( ( 2  +  4 )  *  - 1  )  ^ 2 +  1 )  = 37
6
Edwin Dalorzo

Ich denke, dass Shape eine gute abstrakte Klasse ist. Es gibt sowohl 2D- als auch 3D-Formen. Die 2D-Formen haben normalerweise eine Fläche, während 3D-Formen Volumen haben. Beide können einen "Standort" oder "Massenzentrum" haben.

Einige Vorschläge:

class Shape {..}

class Shape2D extends Shape {...}

class Circle extends Shape2D {...}

class Rectangle extends Shape2D {...}

class Polygon extends Shape2D {...}

class Shape3D extends Shape {...}

class Sphere extends Shape3D {...}
5
SteinNorheim

Als Verehrer von Gegentreffern möchte ich dies gerne teilen:

enter image description here

4
Yasser

Ich schlage "Geräte" vor. Niemand modelliert Tiere wirklich mit Software, aber sie modellieren Geräte.

class Device
{
  void start();
  void stop();
  DeviceStatus status { get; }
}

class VideoDevice : Device
{
  ... methods for any/all video devices ...
}

class DiskDevice : Device
{
  ... methods for any/all disk devices ...
}
3
ChrisW

Ich habe immer gern geliebt:

class Shape {
}
class Square extends Shape {
}

Aber einer der drei besten, die Sie zitieren, wäre in Ordnung. MountainBike klingt am aufregendsten. Ähnliches kann man natürlich auch mit Autos machen.

2
Iain M Norman

Ich mag die Idee, Drucker als Beispiel zu verwenden. Angenommen, Sie arbeiten für HP, Brother, Lexmark oder eine andere Einheit und müssen ein Programm entwickeln, das treiberspezifische Module für verschiedene Betriebssysteme generieren kann.

class Printer {
    private String brand;
    private String model;

    public void powerOn() {
        // Logic to power on
    }

    public void powerOff() {
        // Logic to power off
    }

    public void init() {
        // Bootstrap/prep the system
        // Check cartridge
        // Check paper
        // Ready for usage
}

class InkJetPrinter extends Printer {
    // Inherits fields and methods from Printer
    // Demonstrate method overriding and overloading
    // Add new InkJet specific behaviors, components etc.
}

class LaserPrinter extends Printer {
    // Inherits fields and methods from Printer
    // Demonstrate method overriding and overloading
    // Add new Laser specific behaviors, components etc.
}

class LabelPrinter extends Printer {
    // Inherits fields and methods from Printer
    // Demonstrate method overriding and overloading
    // Add new Label specific behaviors, components etc.
}

Nachdem Sie die Vererbung demonstriert haben, können Sie sich in Richtung Abstraktion bewegen und Methodenüberladung/Überschreibung überschreiben . Die init-Methode in der Printer-Klasse ist ein guter Kandidat für die Abstraktion. Unterklassen müssen ihre eigenen Initialisierungsprozesse implementieren.

Sie können dieses Beispiel auch erweitern und mit der korrekten Verwendung von Schnittstellen und Komposition beginnen. Was ist der Unterschied zwischen einem IS-A- und einem HAS-A-Konzept? Einige Drucker verfügen möglicherweise über WLAN- und Bluetooth-Funktionen. Oder einige InkJet-Drucker verfügen möglicherweise über Scanfunktionen, während andere nur über Zuführungen verfügen. Wie würden Sie dies implementieren?

Ich denke, die Verwendung von Druckern ist generell enger mit Computer und Informatik verbunden. Sie können dieses Beispiel verwenden und noch weitere Beispiele zeigen, die sich mit der Vernetzung zwischen eingebetteten Systemen und PCs, SmartPhones und anderen IoTs befassen.

1
Emir Memic

Webshop könnte auch eine gute Option sein.

Product(id, title, price, description)
Book(isbn, publisher, pageNr) extends Product
CD(company, duration, genre, taskList) extends Product
1
Victor

Ich zeige Schachfiguren. Die Basisklasse ist die allgemeine Vererbung von ChessPiece, King, Rook, Bishop usw. 

Was mir an diesem Beispiel gefällt:

  • wenn Sie Schach implementieren, ist dies eine Lösung
  • in C++ können Sie zeigen, welche Funktion virtuell ist und welche nicht
  • abstrakte Klasse kann gezeigt werden
  • ein fortgeschrittenes Beispiel kann sich in Richtung einer gemeinsamen Basisklasse für Richtungsstücke (Rook und Bishop) oder sogar zu allgemeinen Richtungsstücken mit Stufenbegrenzung (alles außer Pfand) entwickeln
1

Ich mag das Fahrzeugbeispiel, da es eine relativ saubere Erweiterung ermöglicht, um Schnittstellen in die Diskussion einzubeziehen (IAutomaticGearbox, jedermann?)

0
Rowland Shaw

Wie wäre es mit 

class Weapon 
{
}

class Gun : extends Weapon
{
}

class Knife : extends Weapon
{
}

et.

0
Muad'Dib

Vererbung kann komplex sein. Beginnen wir mit der einfachsten aller Verhaltensvererbung. Hier erben Sie nur Verhalten und keinen Zustand. Zum Beispiel: Sowohl Person als auch Animal sind Animationsobjekte, die ein IsAlive-Verhalten zeigen. Um Ihr Beispiel zu verwenden:

class LivingThing {
   /* We propose a new type */
  public:
    virtual bool IsAlive() = 0;
    virtual void Birth() = 0;
    virtual void Death() = 0;
};

class Person : public  LivingThing {
    /* A real living thing */
  public:
    virtual bool IsAlive() { return true; }
    virtual void Birth() {}
    virtual void Death() {}
    /* .. and has some special behavior */
    void Marry();
    void Divorce();
};

class Animal: public  LivingThing {
    /* A real living thing */
  public:
    virtual bool IsAlive() { return true; }
    virtual void Birth() {}
    virtual void Death() {}
    /* .. and has some special behavior */
    void Bite();
    void Bark();
};

Ich habe dies mit der C++ - Syntax geschrieben. Wenn Sie Probleme haben, etwas davon zu verstehen, sagen Sie es einfach!

0
dirkgently

Das beste Beispiel, dem ich begegnet bin (und in vielen Büchern gelesen habe), ist das, das Shape verwendet.

Das Beste daran ist, dass Sie sehr leicht alle Konzepte (einschließlich der harten), die sich auf OOPs beziehen, wie Klasse, Objekt, Vererbung, Abstraktion, Verkapselung, Polymorphismus usw., jedem Programmierer erklären können, der für seine Erfahrung nicht relevant ist.

0
Santosh Gokak

Beispiel:

Der Ansatz "Alles ergibt sich aus Objekt".

Hund -> Tier -> Lebewesen -> Objekt

Ein Hund ist ein Tier, das ein Lebewesen ist, das wiederum ein Objekt ist.

0
Elroy

Beispiele für Klassenvererbung finden Sie in Design-Mustern. 

  1. Abstract_factory_pattern : Bietet eine Möglichkeit, eine Gruppe einzelner Fabriken, die ein gemeinsames Thema haben, zu kapseln, ohne ihre konkrete Klasse anzugeben

  2. Template_method_pattern : Dies ist ein Verhaltensmuster, das das Programmgerüst eines Algorithmus in einer Operation definiert, wobei einige Schritte auf Unterklassen verschoben werden.

  3. Decorator_pattern : Dies ist ein Entwurfsmuster, mit dem das Verhalten einem einzelnen Objekt entweder statisch oder dynamisch hinzugefügt werden kann, ohne das Verhalten anderer Objekte derselben Klasse zu beeinflussen

In den folgenden Beiträgen finden Sie Beispiele aus der Praxis:

Wann das Dekorateur-Muster verwenden?

Template Design Pattern in JDK, konnte keine Methode finden, die eine Menge von Methoden definiert, die in der Reihenfolge ausgeführt werden sollen

0
Ravindra babu