자바와 객체 지향 프로그래밍 (OOP)
객체 지향 프로그래밍
객체 지향 프로그래밍(Object-Oriented Programming)이란 객체(Object)라는 기본 단위로 코드를 나눠 구현하는 패러다임(프로그래밍 설계 방법)을 말한다.
객체 지향 프로그래밍은 코드의 재사용성, 유지보수성, 모듈성(확장성)을 높여준다.
1. 객체 지향의 4가지 특징
1-1. 캡슐화 (Encapsulation)
데이터(변수)와 이를 조작하는 메서드를 하나로 묶고, 외부에서 직접 접근하지 못하도록 보호, 은닉하는 것을 말한다.
Java에서는 접근 제어자를 통해 캡슐화를 실현할 수 있다.
1-2. 상속 (Inheritance)
부모 클래스로부터 자식 클래스를 생성하여, 부모 클래스의 속성과 메서드를 자식 클래스가 재사용할 수 있도록 하는 것을 말한다.
상속을 통해 자식 클래스는 부모 클래스에서 정의된 모든 속성과 메서드를 그대로 사용할 수 있으며, 필요한 경우 이를 확장하거나 재정의(오버라이딩)할 수 있다.
1-3. 다형성 (Polymorphism)
하나의 인터페이스(메서드, 클래스 등)로 여러 기능을 수행할 수 있도록 만드는 것을 의미한다.
Java에서는 오버로딩(Overloading), 오버라이딩(Overriding), 부모 클래스 타입으로 자식 클래스 객체를 참조하는 업캐스팅(Upcasting)이 이에 해당한다.
1-4. 추상화 (Abstraction)
불필요한 세부 사항을 숨기고, 외부에 중요한 정보(핵심 기능)만 제공하는 것을 의미한다.
Java에서는 추상 클래스(Abstract class)와 인터페이스(Interface)를 통해 추상화를 구현할 수 있다.
2. 객체 지향 설계 5원칙 (SOLID)
2-1. 단일 책임 원칙 (Single Responsibility Principle, SRP)
클래스나 모듈이 하나의 책임만 가져야 한다는 것을 의미한다.
하나의 클래스가 많은 기능을 가지고 있을 경우, 해당 클래스의 수정이 여러 곳에 영향을 미치게 된다.
2-2. 개방-폐쇄 원칙 (Open-Closed Principle, OCP)
클래스나 모듈이 확장에 열려 있고, 수정에는 닫혀 있어야 한다는 것을 의미한다.
풀어 말하면, 새로운 기능 추가를 위해 클래스를 확장하여 구현하고, 그 확장에 따른 기존 클래스의 수정은 최소화하는 것이다.
자바에서 추상 클래스의 상속이나 인터페이스의 구현을 떠올리면 된다.
2-3. 리스코프 치환 원칙 (Liskov Substitution Principle, LSP)
자식 클래스가 부모 클래스의 기능을 대체할 수 있어야 한다는 것을 의미한다.
즉, 다형성을 활용하기 위한 원칙으로, 서브 타입을 슈퍼 타입으로 교체할 수 있어야 한다는 것이다.
자바에서 ArrayList 객체를 List 타입으로 초기화해서 사용하는 업캐스팅을 예로 들 수 있다.
2-4. 인터페이스 분리 원칙 (Interface Segregation Principle, ISP)
인터페이스를 가능한 한 작은 단위로 분리해야 한다는 것을 의미한다.
하나의 큰 인터페이스가 아닌 여러 개의 작은 인터페이스로 나누어 필요로 하는 기능만을 의존할 수 있도록 해야 한다는 것이다.
자바에서는 인터페이스를 다중 상속(구현)할 수 있기 때문에, 인터페이스를 작게 나눠도 문제 없다.
2-5. 의존성 역전 원칙 (Dependency Inversion Principle, DIP)
상위 모듈이 하위 모듈에 의존해서는 안되고, 추상화에 의존해야 한다는 것을 의미한다.
즉, 구체 클래스 (Concrete Class)가 아니라 인터페이스나 추상 클래스에 의존해야 한다는 뜻이다.