Vererbung und Zusammensetzung sind zwei grundlegende Konzepte in der objektorientierten Programmierung (OOP), aber sie werden unterschiedlich verwendet und haben unterschiedliche Zwecke. Ziel dieses Beitrags ist es, diese Zwecke zu besprechen und einige Dinge zu besprechen, die bei der Auswahl zu beachten sind.
Wenn wir über die Anwendung der Vererbung in unseren Designs nachdenken, müssen wir Folgendes verstehen:
Andererseits, wenn wir darüber nachdenken, Objekte zusammenzusetzen:
Die Frage, ob Komposition besser ist als Vererbung oder umgekehrt, ist ein umstrittenes Thema im Software-Design. Beide Ansätze haben ihre Vor- und Nachteile und die Wahl hängt vom spezifischen Projektkontext und den Anforderungen ab. Hier präsentiere ich Ihnen ein Beispiel, bei dem die Komposition der Vererbung vorzuziehen sein kann.
Sehen wir uns ein Beispiel in Java an, das zeigt, wie die Komposition in bestimmten Fällen der Vererbung vorzuziehen sein kann. Angenommen, wir arbeiten an einem Bestellabwicklungssystem in einem Online-Shop.
Betrachten wir zunächst einen Ansatz, der Vererbung nutzt, um verschiedene Arten käuflicher Produkte wie Bücher und Elektronik darzustellen:
// Clase base para productos class Producto { String nombre; double precio; Producto(String nombre, double precio) { this.nombre = nombre; this.precio = precio; } void procesarPedido() { System.out.println("Procesando pedido para " nombre); } } // Clase para productos electrónicos que hereda de Producto class ProductoElectronico extends Producto { String modelo; ProductoElectronico(String nombre, double precio, String modelo) { super(nombre, precio); this.modelo = modelo; } } // Clase para libros que hereda de Producto class Libro extends Producto { String autor; Libro(String nombre, double precio, String autor) { super(nombre, precio); this.autor = autor; } }
Dieser Ansatz funktioniert, aber was ist, wenn Sie neue Produkttypen einführen oder bestimmte Funktionen für bestimmte Produkttypen hinzufügen müssen?
Anstatt uns ausschließlich auf die Vererbung zu verlassen, könnten wir die Zusammensetzung verwenden, um verschiedene Arten von Produkten flexibler zu handhaben:
// Clase para productos class Producto { String nombre; double precio; Producto(String nombre, double precio) { this.nombre = nombre; this.precio = precio; } void procesarPedido() { System.out.println("Procesando pedido para " nombre); } } // Clase para productos electrónicos que utiliza composición class ProductoElectronico { Producto producto; String modelo; ProductoElectronico(String nombre, double precio, String modelo) { this.producto = new Producto(nombre, precio); this.modelo = modelo; } // Puedes agregar lógica específica para productos electrónicos si es necesario void procesarPedidoEspecifico() { System.out.println("Procesando pedido específico para " producto.nombre); } } // Clase para libros que utiliza composición class Libro { Producto producto; String autor; Libro(String nombre, double precio, String autor) { this.producto = new Producto(nombre, precio); this.autor = autor; } // Puedes agregar lógica específica para libros si es necesario void procesarPedidoEspecifico() { System.out.println("Procesando pedido específico para " producto.nombre); } }
Bei diesem Ansatz verfügt jeder Produkttyp über eine Instanz der Produktklasse, sodass eine gemeinsame Logik für die Verarbeitung von Bestellungen genutzt werden kann. Darüber hinaus kann jeder Produkttyp mithilfe von Methoden wie „processSpecificOrder()“ über eine eigene spezifische Logik verfügen. Dieses Design ist flexibler und erleichtert die Einführung neuer Produkttypen oder die Änderung typspezifischer Logik, ohne die Vererbungshierarchie zu beeinträchtigen.
Während die Wahl zwischen Vererbung und Komposition beim Softwaredesign vom Kontext und den spezifischen Anforderungen des Problems abhängt, mit dem Sie sich befassen. Hier sind einige Situationen, in denen Sie die Vererbung als geeignetere Option als die Komposition in Betracht ziehen könnten:
class Vehiculo { // ... } class Automovil extends Vehiculo { // ... }
class Animal { void comer() { // Lógica común para comer } } class Perro extends Animal { void ladrar() { // Lógica específica para ladrar } }
class Figura { void dibujar() { // Lógica común para dibujar una figura } } class Circulo extends Figura { void dibujar() { // Lógica específica para dibujar un círculo } } class Cuadrado extends Figura { void dibujar() { // Lógica específica para dibujar un cuadrado } }
Wenn wir weiterhin die Vor- und Nachteile der Vererbung abwägen, besteht eines der Probleme, die aus einer schlechten Vererbung entstehen können, darin, dass wir gegen das Prinzip der Schnittstellentrennung verstoßen würden, das besagt, dass Clients nicht gezwungen werden sollten, sich auf Schnittstellen zu verlassen, die sie nutzen nicht verwenden. Wenn eine Schnittstelle auf eine Weise erweitert wird, die Methoden enthält, die nicht für alle Implementierungen relevant sind, könnten Clients, die diese Schnittstelle verwenden, gezwungen werden, Methoden zu implementieren, die sie nicht benötigen, was zu einem weniger sauberen und schwierigeren Design führen kann pflegen.
Zusammenfassend lässt sich sagen, dass sich die Vererbung auf die Beziehung „ist ein“ konzentriert und zur Modellierung von Klassenhierarchien verwendet wird, während sich die Zusammensetzung auf die Beziehung „hat ein“ konzentriert und dazu verwendet wird, komplexe Objekte aus anderen einfacheren Objekten zu konstruieren. Beide Ansätze haben ihre spezifischen Anwendungsfälle und werden basierend auf der Struktur und Art der Beziehungen im Softwaredesign ausgewählt.
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3