Home > Java > Java > ☕️[Java] Object와 OCP - 2

☕️[Java] Object와 OCP - 2
Java Programming Language Backend

☕️[Java] Object와 OCP - 2.

1️⃣ Object.

  • Java에서 'Object' 는 모든 클래스의 최상위 부모 클래스이자, Java 클래스 계층 구조의 최상위에 위치하는 클래스입니다.
  • Java에서 모든 클래스는 암묵적으로 'Object' 클래스를 상속받으며, 이로 인해 'Object' 클래스가 제공하는 메서드를 사용할 수 있습니다.
    • 이는 Java의 객체 지향 프로그래밍(OOP)에서 중요한 역할을 합니다.

1️⃣ Object 클래스의 주요 역할.

  • 1. 최상위 클래스.
    • 모든 Java 클래스는 'Objcet' 클래스를 상속받기 때문에 'Object' 클래스에서 제공하는 메서드는 모든 객체에서 사용할 수 있습니다.
  • 2. 기본 메서드 제공.
    • 'Object' 클래스는 모든 객체가 기본적으로 사용할 수 있는 몇 가지 중요한 메서드를 제공합니다.
      • 예를 들어 다음과 같습니다.
        • 'equals(Object obj)'
          • 두 객체가 같은지를 비교합니다.
        • 'hashCode()'
          • 객체의 해시 코드를 반환합니다. 이 값은 객체를 식별하는 데 사용됩니다.
        • 'toString()'
          • 객체를 문자열로 표현합니다.
        • 'clone()'
          • 객체를 복제합니다.(단, 클래스에서 'Cloneable' 인터페이스를 구현해야 사용 가능)
        • 'finalize()'
          • 객체가 가비지 컬렉션되기 전에 호출됩니다.
  • 3. 다형성 지원.
    • 'Object' 타입으로 모든 객체를 참조할 수 있으므로, 다양한 객체를 처리하는 메서드나 컬렉션에서 유연성을 제공합니다.
      • 예를 들어, Java의 컬렉션 프레임워크에서는 'Object' 타입을 사용하여 다양한 타입의 객체를 저장할 수 있습니다.
  • 4. 공통 기능의 확장.
    • 모든 클래스가 'Object' 를 상속받기 때문에, 'Object' 클래스의 메서드를 재정의(Override)하여 클래스에 맞는 동작을 구현할 수 있습니다.
      • 예를 들어, 'toString()' 메서드를 재정의하여 객체의 상태를 의미 있는 문자열로 표현할 수 있습니다.

2️⃣ 예시.

  • 다음은 'Object' 클래스의 메서드를 활용하는 간단한 예시입니다.
public class Person {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        
        Person person = (Person) obj;
        
        return age == person.age && name.equals(person.name);
    }
    
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
    
    public static void main(String[] args) {
        Person person1 = new Person("Alice", 30);
        Person person2 = new Person("Alice", 30);
        
        System.out.println(person1.equals(person2)); // true
        System.out.println(person1.toString()); // Person{name='Alice', age=30}
    }
}
  • 이 예시에서 'equals''toString' 메서드는 'Object' 클래스에서 제공하는 메서드를 재정의하여 'Person' 클래스의 객체에 적합한 동작을 정의하고 있습니다.

3️⃣ 결론.

  • Java의 'Object' 클래스는 모든 클래스의 공통 조상으로서 중요한 역할을 하며, 기본적인 객체 비교, 해시 코드 생성, 문자열 표현 등의 기능을 제공합니다.
    • 이는 Java에서의 객체 지향 프로그래밍의 기초를 이루며, 다양한 클래스 간의 상호작용을 가능하게 합니다.

2️⃣ OCP

  • OCP는 “Open/Closed Principle”의 약자로, 객체 지향 설계의 중요한 원칙 중 하나입니다.
    • 이 원칙은 Robert C. Martin에 의해 정의된 SOLID 원칙 중 하나로, 소프트웨어 설계의 유연성과 유지보수성을 높이기 위한 지침을 제공합니다.

1️⃣ OCP(Open/Closed Principle)의 정의

  • “소프트웨어 엔티티(클래스, 모듈, 함수 등)는 확장에 열려 있어야 하고, 수정에는 닫혀 있어야 한다.” 라는 원칙입니다.
    • 확장에 열려 있어야 한다(Open for extension)
      • 새로운 기능이나 요구사항이 추가될 때, 기존 코드를 변경하지 않고도 기능을 확장할 수 있어야 한다는 뜻입니다.
      • 이를 통해 소프트웨어를 유연하게 확장할 수 있으며, 새로운 기능을 도입할 때 기존 코드에 영향을 주지 않게 됩니다.
    • 수정에 닫혀 있어야 한다(Closed for modification)
      • 기존에 잘 작동하던 코드를 수정하지 않고도 새로운 기능을 추가할 수 있어야 한다는 뜻입니다.
      • 이는 소프트웨어의 안정성을 유지하면서 변경의 영향을 최소화할 수 있습니다.

2️⃣ OCP의 구현 방법.

  • OCP를 구현하는 가장 일반적인 방법은 추상화다형성 을 사용하는 것입니다.
    • 추상 클래스나 인터페이스를 통해 기본 구조를 정의하고, 이를 상속하거나 구현하여 구체적인 기능을 확장합니다.
      • 이렇게 하면 기존 코드베이스를 변경하지 않고도 새로운 기능을 추가할 수 있습니다.

3️⃣ 예시.

// 기존 코드: Shape 인터페이스 정의
interface Shape {
    double calculateArea();
}

// 기존 코드: Rectangle 클래스 정의
class Rectangle implements Shape {
    private double width;
    private double height;
    
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    
    @Override
    public double calculateArea() {
        return width * height;
    }
 }

// 확장 코드: Circle 클래스 정의 (기존 코드를 수정하지 않음)
class Circle implements Shape {
    private double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

// 클라이언트 코드
public class Main {
    public static void main(String[] args) {
        Shape rectangle = new Rectangle(10, 20);
        Shape circle = new Circle(5);
        
        System.out.println("Rectangle Area: " + rectangle.calculateArea());
        System.out.println("Circle Area: " + circle.calculateArea());
    }
}

설명

  • 이 예시에서 'Shape' 인터페이스는 면적을 계산하는 'calculateArea()' 메서드를 정의합니다.
  • 'Rectangle' 클래스는 이 인터페이스를 구현하여 사각형의 면적을 계산하는 기능을 제공합니다.
  • 이후, 'Circle' 클래스를 추가하면서 새로운 기능을 확장합니다.
    • 이 과정에서 기존의 'Rectangle' 클래스나 'Shape' 인터페이스의 코드는 전혀 수정하지 않고 새로운 기능을 추가할 수 있었습니다.

이처럼 OCP를 잘 준수하면 소프트웨어가 변화하는 요구사항에 유연하게 대응할 수 있으며, 유지보수 비용을 줄이고 코드의 재사용성을 높일 수 있습니다.

3️⃣ Object와 OCP의 관계.

  • 'Object''OCP(Open/Closed Principle)' 는 둘 다 객체 지향 프로그래밍의 개념과 밀접하게 관련되어 있지만, 그 역할과 목적은 다릅니다.
    • 이 둘의 관계ㄴ를 이해하려면 먼저 각각의 역할을 간단히 요약하고, 그 후에 이들이 어떻게 상호작용하는지 설명할 수 있습니다.

1️⃣ ‘Object’ 클래스의 역할

  • Java에서 'Object' 클래스는 모든 클래스의 최상위 부모 클래스입니다.
    • 모든 Java 클래스는 암묵적으로 'Object' 를 상속받으며, 'Object' 클래스에서 제공하는 메서드를 사용할 수 있습니다.
    • 이 클래스는 Java에서 객체의 기본적인 기능(예: 'equalse', 'hashCode', 'toString')을 제공합니다.
    • 'Object' 클래스 자체는 특정한 설계 원칙을 강제하지 않지만, 객체 지향 프로그래밍의 근본적인 기초를 제공합니다.

2️⃣ OCP(Open/Closed Principle)의 역할.

  • OCP는 소프트웨어 설계 원칙으로, 소프트웨어가 확장에는 열려 있어야 하고, 수정에는 닫혀 있어야 한다 는 원칙을 따릅니다.
    • 이 원틱은 소프트웨어를 설계할 때 변화하는 요구사항에 유연하게 대응하고, 코드의 수정 없이도 기능을 확장할 수 있도록 구조화하는 방법론입니다.
      • 이는 주로 인터페이스, 추상 클래스, 상속, 다형성 등을 통해 구현됩니다.

3️⃣ ‘Object’와 OCP의 관계.

  • 1. 기본 클래스 구조 제공.
    • ‘Object’ 클래스는 모든 클래스의 기본이 되며, OCP 원칙을 적용하기 위한 기본 구조를 제공합니다.
      • 예를 들어, 모든 클래스가 'Object' 를 상속받기 때문에, 클래스 설계자는 'Object' 클래스에서 제공하는 메서드(예: 'equals', 'hashCode') 를 재정의할 수 있습니다.
        • 이를 통해 각 클래스가 자신만의 독특한 행동을 가지도록 확장할 수 있습니다.
  • 2. 추상화와 다형성의 기초.
    • OCP를 실현하기 위해서는 추상화와 다형성이 중요한데, 'Object' 클래스는 이 둘의 기초를 제공합니다.
    • 모든 클래스는 'Object' 타입으로 참조될 수 있으므로, OCP를 구현할 때 다형성을 활용할 수 있습니다.
      • 예를 들어, 다양한 타입의 객체를 'Object' 로 처리하면서도, 각 객체가 특정 행위를 다르게 구현하도록 설계할 수 있습니다.
  • 3, OCP 준수에 대한 도움.
    • 'Object' 클래스는 모든 클래스가 공통적으로 가져야 하는 기본적인 기능을 제공하기 때문에, 설계자는 이 기능을 바탕으로 필요한 부분만 재정의하여 기능을 확장할 수 있습니다.
      • 이는 OCP를 준수하는 데 도움이 됩니다.
        • 예를 들어, 특정 객체가 'equals' 메서드를 새롭게 구현함으로써 비교 방식을 확장하면서도, 기존의 'Object' 클래스 코드를 수정할 필요는 없습니다.

4️⃣ 결론.

  • 'Object' 클래스는 모든 클래스의 기반이 되며, OCP를 준수하는 소프트웨어 설계에 있어 중요한 역할을 합니다.
  • Object 는 직접적으로 OCP를 구현하지 않지만, 그 위에서 개발자들이 OCP 원칙을 적용할 수 있도록 추상화와 다형성의 기초를 제공합니다.
  • OCP를 준수하는 설계를 통해 개발자는 객체 지향 프로그래밍의 이점을 극대화할 수 있습니다.