Language/Java

[Java] 객체 지향 언어

by Donghwan 2021. 9. 29.

객체 지향 프로그래밍(Object-Oriented Programming, OOP)은 프로그래밍의 패러다임 중 하나로 객체의 관점으로 프로그램을 설계하는 방법입니다.

작은 문제들을 해결할 수 있는 객체들을 만든 뒤, 이 객체들을 조합해서 큰 문제를 해결하는 상향식(Bottom-Up) 해결법을 도입했습니다. 이 객체란 것을 일단 한번 독립성/신뢰성이 높게 만들어 놓기만 하면 그 이후에 그 객체를 수정 없이 재사용할 수 있으므로 개발 기간과 비용이 대폭 줄어들게 됩니다.

객체 지향 프로그래밍은 프로그램을 유연하고 변경이 용이하게 만들기 때문에 대규모 소포트웨어 개발에 많이 사용됩니다. 또한 프로그래밍을 더 배우기 쉽게 하고 소프트웨어 개발과 보수를 간편하게 하며, 직관적인 코드 분석을 가능하게 하는 장점을 갖고 있습니다. 그러나 지나친 프로그램의 객체화 경향은 실제 세계의 모습을 그대로 반영하지 못합니다.

 

객체 지향 언어의 특징

1. 상속(Inheritance)
상속은 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것입니다. 상속을 통해서 클래스를 작성하면 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있고 코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경에 용이합니다. 이러한 특징으로 코드의 재사용성을 높이고 코드의 중복을 제거할 수 있습니다.

보통 상속의 관계를 부모와 자식의 관계라고 설명하지만 부모와 자식보단 상위 클래스와 하위 클래스라고 할 수 있습니다. 상위 클래스를 상속받은 하위 클래스는 상위 클래스의 모든 자료와 메소드를 물려받아 자유롭게 사용할 수 있고 거기에 더해 필요한 특성을 추가해서 사용할 수 있습니다. 하지만 접근 제어자의 범위에 따라 상속은 받지만 접근이 제한될 수 있습니다.
2. 다형성(Polymorphism)
다형성은 상속과 함께 객체 지향의 중요한 특징입니다. 객체 지향에서 여러가지 형태를 가질 수 있는 능력을 의미합니다. 좀 더 구체적으로 말하자면 상위 클래스의 참조변수로 하위 클래스의 인스턴스를 참조할 수 있다는 것입니다.

상위 클래스의 참조변수를 하위 클래스의 인스턴스로 참조하였을 때 하위 클래스의 인스턴스를 생성했지만 타입이 상위 클래스이기 때문에 하위 클래스의 변수 또는 메서드를 사용할 수 없습니다. 하지만 반대로 하위 클래스의 참조변수에 상위 클래스의 인스턴스를 생성하는 것은 불가능합니다.
public class A { ... }

public class B extends A { 
   public void click() { ... }
}

public class Main {
   public static void main(String[] args) {
       A sample1 = new B();     //가능
       B sample2 = new B();     //가능
       B sample3 = new A();     //불가능
       B sample4 = (B) new A(); //가능, 하지만 런타임에서 에러가 발생
       B sample5 = (B) sample1; //가능, 런타임에서도 문제 없음
       
       sample1.click()      //B를 인스턴스로 사용했지만 A타입이기 때문에 사용 불가능
       sample2.click();     //B 타입이기 때문에 사용 가능
   }
}

이 때 하위 클래스의 참조변수에 상위 클래스의 인스턴스를 생성하는 것을 가능하게 하려면 형변환이 필요합니다. 하위 클래스에서 상위 클래스로 변하는 Up-Casting은 생략이 가능하지만 상위 클래스가 하위 클래스로 변하는 Down-Casting은 생략이 불가능하고 예제처럼 명시적으로 표시해줘야 합니다.

그리고 Down-Casting 과정에서 sample4와 sample5를 보면 같은 Down-Casting인데 실행 결과가 다릅니다. 이유는 형변환은 참조변수의 타입을 변환하는 것이지 인스턴스를 변화시키는게 아닙니다. 따라서 A 클래스를 인스턴스화한 sample4의 경우는 에러가 발생하고 B 클래스를 인스턴스화한 sample5는 에러가 발생하지 않는 것입니다.

추가적으로 다형성과 가장 관련이 깊은 것이 바로 인터페이스라고 볼 수 있습니다. 인터페이스는 클래스의 공통적인 행동을 표준화하여 서로 관계없는 클래스들에게 행동으로 관계를 맺어줄 수 있습니다.

public interface Runnable {
    void run();
}

public class Human implements Runnable{
    @Override
    public void run() { ... }
}

public class Rabbit implements Runnable{
    @Override
    public void run() { ... }
}

public class Main {
    public static void main(String[] args) {
        startRun(new Human());
        startRun(new Rabbit());
    }

    public static void startRun(Runnable runnable) {
        runnable.run();
    }
}

//Result
//Human Run
//Rabbit Run

 

위 예제처럼 인터페이스를 이용하면 클래스의 선언과 구현을 분리시켜 독립적으로 프로그래밍을 할 수 있습니다.

3. 추상화(Abstraction)
객체에서 공통된 속성과 행위를 추출하는 것을 추상화라고 합니다. 쉽게 모델링하는 작업이라고 생각할 수 있습니다. 예를 들자면 위의 예제에서 사람과 토끼는 달릴 수 있다는 공통의 행위를 추출하여 Runnable이라는 인터페이스로 추상화하였다고 할 수 있습니다.
4. 캡슐화(Encapsulation)
객체의 속성(data fields)과 행위(메서드, methods)를 하나로 묶고, 실제 구현 내용 일부를 외부에 감추어 은닉한다는 개념을 가지고 있습니다. 변수와 함수를 하나로 묶는 것은 결국 Class화 한다는 의미라고 할 수 있습니다. 또 정보에 대해 은닉은 접근제어자(private, default, protected, public)을 통해 정보의 접근을 관리하는 것을 의미합니다.

 


참고자료

  • 자바의 정석
728x90
반응형

'Language > Java' 카테고리의 다른 글

[Java] 변수 (Variable)  (0) 2021.10.16
[Java] SOLID  (0) 2021.09.29
[Java] 제네릭 (Generic)  (0) 2021.04.21
[Java] 다형성  (0) 2021.01.01
[Java] 실행 데이터 영역 (Runtime Data Area)  (0) 2020.12.27

댓글