"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > 구성과 상속

구성과 상속

2024-11-09에 게시됨
검색:292

Composición vs Herencia

소개

상속과 구성은 객체 지향 프로그래밍(OOP)의 두 가지 기본 개념이지만 서로 다르게 사용되고 서로 다른 목적을 가지고 있습니다. 이 게시물의 목적은 이러한 목적과 이를 선택할 때 염두에 두어야 할 몇 가지 사항을 검토하는 것입니다.

상속의 개념

디자인에 상속을 적용할 때 다음 사항을 이해해야 합니다.

  • 정의: 상속에서 클래스(파생 클래스 또는 하위 클래스라고 함)는 다른 클래스(기본 클래스 또는 슈퍼클래스라고 함)에서 속성과 동작을 상속받을 수 있습니다. 파생 클래스는 기본 클래스의 기능을 확장하거나 수정할 수 있습니다.
  • 관계: "is-a"(is-a) 관계입니다. 예를 들어, "Vehicle" 클래스와 "Car" 클래스가 있는 경우 "Car" 클래스는 "Vehicle"의 하위 클래스입니다.
  • 장점: 코드 재사용을 촉진하고 기능을 쉽게 확장할 수 있습니다.

구성 개념

반면에 객체를 함께 구성하는 것에 대해 생각해 보면:

  • 정의: 구성에서 개체는 다른 개체를 포함하고 해당 기능의 일부를 해당 개체에 위임합니다. 상속 대신 클래스는 다른 클래스의 인스턴스를 사용하여 기능을 달성합니다.
  • 관계: "갖고 있는" 관계입니다. 예를 들어, "Engine" 클래스와 "Car" 클래스가 있는 경우 "Car" 클래스는 "Engine" 클래스의 개체를 가질 수 있습니다.
  • 장점: 유연성이 뛰어나고 클래스 간의 결합이 적습니다. 한 클래스의 변경 사항은 다른 클래스에 직접적인 영향을 미치지 않습니다.

상속에 대한 구성이 필요한 이유는 무엇입니까?

구성이 상속보다 나은지 아니면 그 반대인지에 대한 질문은 소프트웨어 설계에서 논쟁의 여지가 있는 주제입니다. 두 접근 방식 모두 장점과 단점이 있으며 선택은 특정 프로젝트 상황과 요구 사항에 따라 달라집니다. 여기에서는 상속보다 구성이 더 나은 예를 제시하겠습니다.

어떤 경우에는 상속보다 구성이 어떻게 더 선호될 수 있는지 보여주는 Java의 예를 살펴보겠습니다. 온라인 상점의 주문 처리 시스템을 작업한다고 가정해 보겠습니다.

  • 상속 접근 방식:

먼저 책, 전자제품 등 다양한 유형의 구매 가능한 제품을 나타내기 위해 상속을 사용하는 접근 방식을 고려해 보겠습니다.

// 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;
    }
}

이 접근 방식은 효과적입니다. 하지만 새로운 제품 유형을 도입하거나 특정 제품 유형에 특정 기능을 추가해야 하는 경우에는 어떻게 해야 합니까?

  • 작곡에 중점을 둡니다:

상속에만 전적으로 의존하는 대신 구성을 사용하여 다양한 유형의 제품을 보다 유연하게 처리할 수 있습니다.

// 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);
    }
}

이 접근 방식에서는 각 제품 유형에 Product 클래스의 인스턴스가 있으므로 주문 처리를 위해 공통 논리를 공유할 수 있습니다. 또한 각 제품 유형은 processSpecificOrder()와 같은 메서드를 사용하여 고유한 특정 논리를 가질 수 있습니다. 이 디자인은 더 유연하며 상속 계층 구조에 영향을 주지 않고 새로운 제품 유형을 도입하거나 유형별 논리를 수정하기가 더 쉽습니다.

상속은 언제 적용하나요?

소프트웨어 디자인에서 상속과 구성 사이의 선택은 해결하려는 문제의 상황과 특정 요구 사항에 따라 달라집니다. 다음은 구성보다 상속을 더 적절한 옵션으로 고려할 수 있는 몇 가지 상황입니다.

  • "is-a" 관계: 상속은 클래스 간에 명확한 "is-a" 관계가 있을 때 특히 적합합니다. 클래스 B가 클래스 A의 보다 구체적이거나 특수화된 버전인 경우 상속이 적합합니다. 예를 들어 Vehicle 클래스와 Car 클래스가 있는 경우 자동차는 차량 유형이므로 "is-a" 관계가 명확합니다.
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
    }
}

  • 기능 확장: 기존 기능을 확장하거나 특수화하는 경우 상속이 더 자연스러울 수 있습니다. 예를 들어, 라이브러리를 개발 중이고 기본 기능이 포함된 기본 클래스를 제공하는 경우 라이브러리 사용자는 해당 기본 클래스에서 파생되어 해당 기능을 확장할 수 있습니다.

나쁜 유산을 물려주면 어떻게 되나요?

상속의 장단점을 계속 평가한다면 잘못된 상속으로 인해 발생할 수 있는 문제 중 하나는 클라이언트가 자신이 사용하는 인터페이스에 의존하도록 강요해서는 안 된다는 인터페이스 분리 원칙을 위반하게 된다는 것입니다. 사용하지 마십시오. 모든 구현과 관련되지 않은 메소드를 포함하는 방식으로 인터페이스가 확장되면 해당 인터페이스를 사용하는 클라이언트는 필요하지 않은 메소드를 구현하거나 의존하게 되어 덜 깨끗하고 디자인이 더 어려워질 수 있습니다. 유지하다.

결론

요약하자면 상속은 "is a" 관계에 초점을 맞추고 클래스 계층 구조를 모델링하는 데 사용되는 반면, 구성은 "has a" 관계에 초점을 맞추고 다른 단순한 객체로부터 복잡한 객체를 구성하는 데 사용됩니다. 두 접근 방식 모두 고유한 사용 사례가 있으며 소프트웨어 설계 관계의 구조와 특성을 기반으로 선택됩니다.

릴리스 선언문 이 글은 https://dev.to/rlgino/composicion-vs-herencia-4664?1에서 복제됩니다.1 침해 내용이 있는 경우, [email protected]으로 연락하여 삭제하시기 바랍니다.
최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3