
자바는 객체지향 프로그래밍(OOP) 방법론을 적용하는 언어로, OOP의 4가지 특성(캡슐화, 추상화, 다형성, 상속)을 구현하기 위한 다양한 기능을 제공합니다. 이러한 기능들은 객체지향 설계의 원칙을 따르며, 효율적이고 유지보수 가능한 소프트웨어를 개발할 수 있도록 돕습니다.
자바가 제공하는 클래스, 추상 클래스, 인터페이스와 같은 다양한 기능들을 독립적으로 생각하면, 각 문법의 기능만을 이해할 수 있습니다. 예를 들어, Class는 정보(필드)와 행동(메서드)의 집합을 구현하는 설계도이며, extends는 상속을 구현하기 위한 키워드입니다. abstract가 붙은 Class는 추상 클래스로, 인스턴스를 생성할 수 없고 추상 메서드를 포함할 수 있는 클래스입니다. 또한, interface는 implements를 통해 클래스가 구현해야 할 메서드를 정의하는 계약을 제공합니다.
하지만 각 문법이 제공하는 기능을 이해하는 것만큼 중요한 것은, 이 문법들이 어떤 목적을 위해 사용되는지와 그 맥락을 이해하는 것입니다. OOP의 관점에서 각 도구가 제공되는 이유와 사용되는 상황을 제대로 이해해야, 자바에서 제공하는 다양한 도구를 효과적으로 활용할 수 있습니다.
따라서 이번 포스팅에서는 클래스, 추상 클래스, 인터페이스 각각의 사용 이유와 필요성을 OOP의 관점에서 정리하고, 자바가 왜 이 세 가지 도구를 제공하는지에 대해 깊이 있게 분석해보겠습니다.
클래스는 객체 지향 프로그래밍(OOP)의 가장 기본적인 구성 요소로, 정보와 행동을 하나의 단위로 묶는 역할을 합니다. 자바에서 클래스는 실제 동작하는 객체를 만들기 위한 설계도이자 구체적인 구현체로, 추상화와 캡슐화를 구현하는 주 도구라고 할 수 있습니다.
클래스는 추상화의 도구
추상화는 복잡한 시스템을 단순화하고, 핵심적인 정보에 집중할 수 있게 해주는 OOP의 4대 특성 중 하나입니다. 클래스는 이 추상화 개념을 정보와 행동을 하나의 단위로 묶는 방식으로 구현할 수 있습니다.
예를 들어, 자동차라는 현실 세계의 객체를 생각해 보겠습니다. 자동차는 추상적으로 보면 모델, 색상, 속도와 같은 공통적인 특성을 가지고 있으며, 가속, 주행, 정지와 같은 행동을 가집니다. 이 모든 특성과 행동은 구체적인 구현이 아니라, 자동차라는 추상적인 개념을 나타내는 특성들입니다.
클래스는 바로 이런 추상적인 특성들을 하나로 묶는 역할을 합니다. 클래스를 통해 우리는 자동차 객체를 구체적으로 생성할 수 있습니다. 즉, 클래스는 추상화된 설계에 맞춰 실제로 동작하는 객체를 만들 수 있게 해주는 중요한 도구입니다.
따라서, 클래스는 객체를 생성할 수 있다는 특별한 기능을 통해, 추상화된 설계를 구체화하며, 동시에 정보와 행동을 하나로 묶는 역할을 합니다.
클래스는 캡슐화의 도구
캡슐화는 객체의 내부 상태(필드)를 외부에서 직접 접근할 수 없도록 숨기고, 메서드를 통해서만 접근할 수 있게 하는 기법입니다. 이렇게 함으로써, 객체의 내부 구현이 외부에서 직접 조작되지 않도록 보호할 수 있고 이를 통해 데이터 무결성을 유지하고, 변경에 강한 설계를 가능하게 합니다.
클래스는 단순히 정보와 행동을 하나로 묶는 설계를 넘어서, 어떤 정보와 행동을 외부에 노출할지, 어떤 기능을 보호할지에 대한 결정을 내립니다. 즉, 클래스는 클라이언트가 접근할 수 있는 정보와 행동을 관리하는 도구로서, 캡슐화를 통해 복잡성을 줄이고 유지보수성을 높이는 역할을 합니다.
정리하자면 클래스는 정보와 행동을 하나로 묶어 객체를 정의하며, 이 객체가 실제 동작하는 구현체로 사용될 수 있도록 하는 것이 주 목적이고 이에 따라 추상화와 캡슐화를 통해 복잡한 시스템을 단순화하고, 데이터 보호와 기능을 관리하는 도구로서 핵심적인 역할을 수행하게 됩니다.
클래스를 사용하는 목적
추상 클래스는 상속을 주 목적으로 하는 도구입니다. 추상 클래스는 구체적인 구현을 제공할 수 있으며, 동시에 추상 메서드를 포함하여 자식 클래스에서 이를 구체화하도록 강제합니다. 추상 클래스는 인스턴스를 생성할 수 없고, 상속을 통해 자식 클래스에서 구체적인 구현을 하도록 유도합니다.
추상 클래스는 추상 메서드뿐만 아니라 일반적인 메서드와 필드도 포함할 수 있습니다. 하지만 인스턴스화할 수 없고, 추상 메서드를 상속받은 자식 클래스는 반드시 이를 구현해야 한다는 점이 클래스와 다른 점입니다.
바로 이러한 특징은 상속에 필요한 기능들을 모두 포함하고 있습니다. 상속에서 중요한 것은 클래스를 통한 생성이 아닌 부모 클래스가 제공하는 필드나 메서드, 부모 클래스 타입을 자식 클래스가 상속받을 수 있도록 하는 것이기 때문에 이와 관련된 기능들만 제공하는 추상 클래스의 주 목적은 상속이라는 것을 유추할 수 있습니다.
저는 상속은 확장성을 의미하며, 추상 클래스는 결과적으로 확장성을 높여주는 도구라고 생각합니다.
따라서 추상 클래스는 공통된 구현을 공유하면서 상속을 통해 기능을 확장하고자 할 때 필요한 도구입니다.
추상 클래스를 사용하는 목적
인터페이스는 추상 클래스와 유사하게 인스턴스를 생성할 수 없고, 완전한 구현을 제공할 수 없습니다. 대신, 인터페이스는 구현해야 할 메서드를 선언만 해 놓고, 이를 구현한 클래스에서 구체적으로 구현하도록 합니다. 이러한 특징은 다형성을 구현하는 데 필요한 기본적인 특성만을 제공합니다.
인터페이스는 추상 클래스처럼 타입 클래스를 상속할 수 있으며, 구체적인 필드나 기능을 자식 클래스에서 사용할 수 없습니다. 오로지 타입만을 제공하여, 해당 타입을 구현하는 클래스들이 일관된 동작을 하도록 합니다. 이를 통해 다형성을 구현하고, 여러 클래스들이 동일한 메서드를 다르게 구현할 수 있게 합니다.
인터페이스는 안정성 있게 다형성을 구현할 수 있는 도구로, 클라이언트는 인터페이스를 알고 있으면, 해당 인터페이스를 구현한 클래스가 어떤 방식으로 동작하는지 알지 못해도, 어떤 메서드를 사용할 수 있다는 것을 보장할 수 있습니다.
인터페이스를 사용하는 목적
자바가 제공하는 클래스, 추상 클래스, 인터페이스는 각각 OOP의 핵심 원칙인 추상화, 캡슐화, 상속, 다형성을 구현하는 데 중요한 역할을 합니다. 물론 OOP을 구현하는 하는 방법은 상호 보완적이고 다른 기능으로도 충분히 구현 가능합니다만 각각의 기능들의 주 목적이 무엇인지를 정리한 것이니 오해 않으셨으면 좋겠습니다.