객체지향 프로그래밍(OOP) 기초

dakcoh·2024년 9월 19일

이번 글에서는 Java의 기초 개념인 객체지향 프로그래밍 (OOP)에 대해 알아보겠습니다.

객체지향은 Java의 핵심 개념이며,
이를 제대로 이해하면 더욱 견고하고 유지보수하기 쉬운 코드를 작성할 수 있습니다.

객체지향 프로그래밍이란?

객체지향 프로그래밍은 실세계의 객체(Object)를 소프트웨어로 모델링하는 방식입니다.
객체는 속성 (Property)행동 (Behavior)을 가지고 있으며, 이를 통해 프로그램이 동작합니다.

객체지향의 4대 핵심 개념은 다음과 같습니다.

1. 캡슐화 (Encapsulation)
2. 상속 (Inheritance)
3. 다형성 (Polymorphism)
4. 추상화 (Abstraction)

아래에서 각각의 개념과 코드 예제를 통해 자세히 알아보겠습니다.


1. 캡슐화 (Encapsulation)

캡슐화는 데이터를 외부에서 직접 접근하지 못하도록 숨기고, 필요한 접근은 메서드를 통해 이루어지도록 하는 것입니다.

코드 예제

public class Person {
    private String name; // 외부에서 직접 접근 불가
    private int age;

    // 생성자
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getter와 Setter를 통해 접근 허용
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age > 0) { // 유효성 검사
            this.age = age;
        }
    }
}

설명

  • nameage 필드는 private으로 선언되어 외부에서 직접 접근할 수 없습니다.
  • 대신, getName(), setName(), getAge(), setAge() 메서드를 통해 접근합니다. 이를 통해 데이터 보호와 유효성 검사를 쉽게 할 수 있습니다.

2. 상속 (Inheritance)

상속은 기존 클래스의 속성과 메서드를 재사용하고, 새로운 기능을 추가하는 방식입니다.

코드 예제

// 부모 클래스
public class Animal {
    public void eat() {
        System.out.println("This animal eats food.");
    }
}

// 자식 클래스
public class Dog extends Animal {
    public void bark() {
        System.out.println("The dog barks.");
    }
}

// 메인 메서드
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat(); // 부모 클래스 메서드 사용
        dog.bark(); // 자식 클래스 메서드 사용
    }
}

설명

  • Dog 클래스는 Animal 클래스를 상속받아 eat() 메서드를 사용할 수 있습니다.
  • 상속을 통해 코드 재사용성이 향상됩니다.

3. 다형성 (Polymorphism)

다형성은 하나의 객체가 여러 형태를 가질 수 있는 특성을 의미합니다.
이를 통해 코드의 유연성과 확장성을 높일 수 있습니다.

코드 예제

public class Animal {
    public void sound() {
        System.out.println("Some generic animal sound");
    }
}

public class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Woof woof");
    }
}

public class Cat extends Animal {
    @Override
    public void sound() {
        System.out.println("Meow");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal1 = new Dog(); // 업캐스팅
        Animal animal2 = new Cat();

        animal1.sound(); // "Woof woof"
        animal2.sound(); // "Meow"
    }
}

설명

  • 부모 클래스 타입의 참조 변수(Animal)로 자식 클래스 객체(Dog, Cat)를 참조할 수 있습니다.
  • sound() 메서드는 각 객체에 따라 다르게 동작합니다 (메서드 오버라이딩).

4. 추상화 (Abstraction)

추상화는 중요한 정보만 노출하고, 불필요한 세부 정보는 숨기는 것입니다.
이를 통해 복잡성을 줄이고, 설계를 개선할 수 있습니다.

코드 예제

// 추상 클래스
public abstract class Shape {
    public abstract double getArea(); // 추상 메서드
}

// 구체 클래스
public class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
}

public class Main {
    public static void main(String[] args) {
        Shape circle = new Circle(5);
        System.out.println("Circle Area: " + circle.getArea());
    }
}

설명

  • Shape 클래스는 추상 클래스이며, getArea()는 구현되지 않은 추상 메서드입니다.
  • Circle 클래스가 이를 구현하여 구체적인 동작을 제공합니다.

객체지향 프로그래밍의 장단점

객체지향 프로그래밍(OOP)을 사용하면 얻을 수 있는 주요 장점은 다음과 같습니다.

➤ 장점

장점설명
- 재사용성 (Reusability)기존 코드를 재사용하여 개발 시간을 단축하고 효율성을 높일 수 있습니다.
- 유지보수성 (Maintainability)코드의 모듈화로 변경 및 수정이 쉬워지고, 코드의 품질을 향상시킬 수 있습니다.
- 확장성 (Scalability)새로운 기능 추가가 용이하며, 다형성을 통해 시스템 확장이 간단해집니다.
- 보안성 (Security)캡슐화를 통해 데이터에 대한 접근을 제한하고, 민감한 정보를 보호할 수 있습니다.
- 유연성 (Flexibility)객체 간의 상호작용을 통해 다양한 상황에 유연하게 대처할 수 있습니다.

➤ 단점

단점설명
- 복잡성 (Complexity)객체와 클래스 간의 관계가 많아지면 설계와 구현이 복잡해질 수 있습니다.
- 성능 저하 (Performance)객체지향은 다형성과 동적 바인딩 때문에 절차지향보다 속도가 느릴 수 있습니다.
- 학습 곡선 (Learning Curve)OOP 개념과 디자인 패턴을 익히는 데 시간이 필요합니다.
- 과도한 설계 (Overhead)지나치게 객체지향적으로 설계하면, 실제 필요 이상으로 구조가 복잡해질 수 있습니다.
- 메모리 사용량 증가(Memory Usage)객체가 많아질수록 메모리 소비가 늘어나 시스템에 부담을 줄 수 있습니다.

객체지향 설계의 핵심

  1. SOLID 원칙을 지켜 설계하면 코드 유지보수가 용이합니다.
  2. getter/setter 남발은 캡슐화를 저해할 수 있으니 주의하세요.
  3. 객체지향 개념을 활용해 설계 단계에서 클래스 간 의존성을 최소화하세요.
  4. 테스트 코드 작성을 통해 객체지향 설계를 검증하세요.

객체지향 개념을 이해하고 잘 활용하면, 보다 정돈된 설계와 구현이 가능합니다.
다음 글에서는 객체지향 설계 원칙(SOLID)에 대해 공부해보겠습니다.

profile
포기하기 금지

0개의 댓글