본문 바로가기
OOP

[OOP] 객체지향의 4대 특징 - 캡슐화, 추상화, 상속, 다형성

by 태크민 2024. 6. 10.

캡슐화

연관된 데이터(변수)와 기능(메소드)을 하나로 묶고, 불필요한 요소를 외부에 노출되지 않도록 설계하는 방식을 뜻한다. 자바에서는 접근 제어자(public, private, default, protected)를 통해 캡슐화를 구현할 수 있다.

class Student {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

public class 캡슐화_예제 {
    
    public static void main(String[] args) {
        Student s1 = new Student();

        // 직접적인 접근은 할 수 없다.
        // s1.id = 1;
        // s1.name = "choi";
        
        // public 접근 제어자인 getter와 setter를 통해 값에 접근할 수 있다.
        s1.setId(1);
        s1.setName("choi");
    }
    
}

이 밖에도 캡슐화를 통해 다음과 같은 효과를 얻을 수 있다.

  • 느슨한 결합
  • 재사용
  • 정보은닉

 

 

 

추상화

추상화는 클래스들의 공통적인 요소를 뽑아서 상위 클래스를 만들어내는 것이다. 한 마디로 추상화는 공통적인 속성과 기능을 정의함으로써 코드의 중복을 줄이고, 클래스 간 관계를 효과적으로 설정하고, 유지보수를 용이하게 하는 것이다.
자바에서는 추상 클래스와 인터페이스라는 문법 요소를 통해 추상화를 구현할 수 있다.

 

 

 

상속

기존의 클래스에 기능을 추가하거나 재정의하여 새로운 클래스를 정의하는 것을 의미한다. 상속을 이용하면 기존에 정의되어 있는 클래스의 모든 필드와 메서드를 물려받을 수 있다. 이로 인하여 다음과 같은 장점을 얻을 수 있다.

  • 기존에 작성된 클래스를 재활용할 수 있다.
  • 자식 클래스 설계 시 중복되는 멤버를 미리 부모 클래스에 작성해 놓으면, 자식 클래스에서는 해당 멤버를 작성하지 않아도 된다.
  • 클래스 간의 계층적 관계를 구성함으로써 다형성의 문법적 토대를 마련한다. 

 

 

다형성

하나의 객체나 메서드가 여러 가지 다른 형태를 가질 수 있는 것을 뜻한다.
자바에서는 이러한 다형성을 이용하여 부모-자식 관계의 클래스들이 존재할 때, 부모 클래스로 자식 클래스들을 서로 다르게 동작시킬 수 있다.
만약 새, 고양이, 강아지라는 클래스가 있고 모두 cry()라는 울음소리를 낼 수 있는 메서드가 있다고 가정해 보자.
각 각의 클래스를 만들고 cry()를 호출하기 위해서는 아래와 같은 코드가 될 것이다.

class Bird {
    void cry() {
        System.out.println("짹짹");
    }
}

class Cat {
    void cry() {
        System.out.println("야옹");
    }
}

class Dog {
    void cry() {
        System.out.println("멍멍");
    }
}

public class 다형성_예제 {

    public static void main(String[] args) {
        Bird bird = new Bird();
        Cat cat = new Cat();
        Dog dog = new Dog();

        bird.cry(); // 짹짹
        cat.cry(); // 야옹
        dog.cry(); // 멍멍
    }

}

하지만, 부모 클래스를 정의한 후 다형성을 활용한다면 아래와 같이 보다 간결한 코드를 만들 수 있게 될 것이다.

abstract class Animal {
    void cry() {}
}

class Bird extends Animal {
    void cry() {
        System.out.println("짹짹");
    }
}

class Cat extends Animal {
    void cry() {
        System.out.println("야옹");
    }
}

class Dog extends Animal {
    void cry() {
        System.out.println("멍멍");
    }
}

public class 다형성_예제 {

    public static void main(String[] args) {
        Animal[] animals = new Animal[]{new Bird(), new Cat(), new Dog()};
        for (Animal animal : animals) {
            animal.cry(); // 짹짹, 야옹, 멍멍
        }
    }

}

이 밖에도 오버라이딩과 오버로딩도 다형성의 일종이라고 볼 수 있다.

 

 

'OOP' 카테고리의 다른 글

[OOP] 정적 바인딩 vs 동적 바인딩  (4) 2024.11.06
[OOP] SOLID, 좋은 객체지향 설계의 5가지 원칙  (1) 2024.09.22