[객체지향] 4가지 특징
해당 내용은 인프런의 즐거운 자바 를 보고 정리한 내용입니다!
객체지향
객체지향 프로그래밍은 내가 만들 객체들이 메모리에 올라간 후, 어떻게 서로 관계를 맺고 동작할 지가 정리돼야 할 수 있다.
엘런 커티스 케이는 객체 지향의 핵심은 "메시징"이라고 했다.
훌륭하고 성장 가능한 시스템을 만들기 위한 핵심은 모듈(클래스) 내부의 속성(필드)과 행동(메서드)이 어떤가보다 모듈이 어떻게 커뮤니케이션하는가에 달려있다.
즉, 객체들 간에 커뮤니케이션이 일어난다는 의미이다.
그렇다면 메시징은 무엇인가?
어떤 객체가 다른 객체의 메소드를 어떻게 호출하는 것을 우리는 메시징이라고 한다.
객체지향 프로그래밍을 한다는 것은 메소드가 언제 호출되고, 어떻게 호출되고, 메소드의 이름은 어떻게 지어야하는지 어떻게 호출해야하는지 고민을 해야한다.
객체는 자율적인 책임을 가진다.
자율적인 객체란 스스로 정한 원칙에 판단하고 스스로의 의지를 기반으로 행동하는 객체다. 객체가 어떤 행동을 하는 유일한 이유는 다른 객체로부터 요청을 수신했기 때문이다. 요청을 처리하기 위해 객체가 수행하는 행동을 책임이라고 한다.
자율적인 책임의 특징은 객체가 어떻게 해야 하는가가 아니라 무엇을 해야하는가를 설명한다는 것이다.
출처: 객체지향의 사실과오해(출판사: 위키북스, 저자: 조영호)
요청이라는 메세지가 객체에 간다는 것은 메소드를 호출하는 것을 의미한다.
객체지향 프로그래밍
객체지향 프로그래밍(Object-Oriented Programming, OOP)은 컴퓨터 프로그래밍의 패러다임 중 하나이다. 객체 지향 프로그래밍은 컴퓨터 프로그램을 명령어의 목록을 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 "객체"들의 모임으로 파악하고자 하는 것이다. 각각의 객체는 메세지를 주고 받고, 데이터를 처리할 수 있다.
출처: https://ko.wikipedia.org/wiki/객체_지향_프로그래밍
클래스(class), 오브젝트(object), 인스턴스(instance), 참조형 변수(Reference Variable)
예를 들어,
설계 도면을 보고 실제 책상을 만들게 되는데 나무를 자르던가, 플라스틱을 이용하던가 해서 직접 만들게 된다.
이렇게 실제 만들어진 책상을 오브젝트(object) 또는 인스턴스(instance)라고 부른다.
우리는 클래스 지향 프로그래밍이라고 말하지 않고 객체 지향 프로그래밍이라고 한다.
객체지향 프로그래밍이라고 말하는 이유가 무엇인가?
클래스를 이용하는게 아니라, 실제 만들어진 객체(오브젝트 또는 인스턴스)를 이용하는 것이다.
설계 도면 = 클래스 / 책상 = 객체(인스턴스)
즉, 클래스를 어떻게 만들까?를 고민하는게 아니라 메모리 상에 존재하는 오브젝트를 어떻게 만들까? 인스턴스를 어떻게 이용할까를 고민하는 것이 중요하다.
객체 지향의 특징 4가지
1) 추상화(Abstract)
- 사물이나 표상을 어떤 성질, 공통성, 본질에 착안하여 그것을 추출하여 파악하는 것
- 즉, 객체의 공통적인 속성과 기능을 추출하여 정의하는것
자바에서 추상화를 구현할 수 있는 문법 요소로는 추상 클래스(abstract class)와 인터페이스(interface)가 있다.
추상 클래스 상속 받은 자식 클래스는 추상 클래스에서 정의하고 있는 추상 메소드를 오버라이드(재정의)를 해야한다.
그 외, 따로 자식 클래스가 필요에 따라 일반 메소드를 정의하여 사용할 수 있고 생성자, 필드도 포함할 수 있다.
인터페이스는 구현하고 있는 구현 클래스는 인터페이스가 정의한 메소드만 오버라이드(재정의)해서 사용할 수 있다. 추상 클래스와 같이 따로 구현 클래스가 메소드를 정의할 수 없다!!
abstract class Animal {
abstract void cry();
// 일반 메소드 작성 가능
}
class Cat extends Animal {
void cry() {
System.out.println("냐옹냐옹!");
}
}
class Dog extends Animal {
void cry() {
System.out.println("멍멍!");
}
}
2) 상속성(Inheritance)
- 상위 클래스(부모)로부터 상속 받는 하위 클래스(자식)들이 상위 클래스의 속성(static 변수)과 기능(메소드)들을 사용할 수 있도록 한다.
public class Mother {
int kind;
String love;
void MotherPersonality () {
System.out.println("조용한 성격이다.");
}
}
public class sun extends Mother {
@Overide
void MotherPersonality () {
System.out.println("조금 조용한 성격이다.");
}
void personality() {
System.out.println("장난끼가 있다.");
}
}
3) 다형성(polymorphism)
- 하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미.
- ⭐클래스는 상속을 통해 확장될 수는 있어도 축소될 수는 없으므로, 자식 클래스에서 사용할 수 있는 멤버의 개수가 언제나 부모 클래스와 같거나 많게 된다.
1. 서로 상속 관계에 있는 클래스 사이에만 타입 변환을 할 수 있습니다.
2. 자식 클래스 타입에서 부모 클래스 타입으로의 타입 변환은 생략할 수 있습니다.
3. 하지만 부모 클래스 타입에서 자식 클래스 타입으로의 타입 변환은 반드시 명시해야 합니다.
=> 멤버의 개수가 줄어들면 안되기 때문
instanceof 를 사용하여 해당 객체의 참조 객체인지 확인 가능하다.
- 일반 클래스를 참조 타입으로 사용하는 경우
class Parent { ... }
class Child extends Parent { ... }
...
Parent pa = new Parent(); // 허용
Child ch = new Child(); // 허용
Parent pc = new Child(); // 허용
Child cp = new Parent(); // ⭐ 오류 발생. // Child 참조변수에 의해 Parent의 멤버 개수가 줄어들게된다.
- 배열 클래스
public class Main {
public static void main(String[] args) {
Car car = new Car();
MotorBike motorBike = new MotorBike();
// 다형성을 활용한 객체 생성 방식
Vehicle car2 = new Car();
// 상위 클래스 타입의 객체 배열 생성
Vehicle vehicles[] = new Vehicles[2];
Vehicles[0] = new Car();
Vehicles[1] = new MotorBike();
for (Vehicle vehicle : Vehicles) {
System.out.println(vehicle.getClass());
}
}
}
- 세 개의 클래스와 한 개의 인터페이스가 있다.
- Car, MotorBike -> Vehicle(인터페이스)
- Driver
- 해당 코드도 아직 객체에 직접적으로 의존하고 있는 문제가 있다.
- 이를 해결하기 위해 스프링 프레임워크의 핵심적인 개념인 의존관계 주입(dependency injection)를 사용할 수 있다.
public class Main {
public static void main(String[] args) {
# new Car() 와 new MotorBike() 처럼 객체에 직접적으로 의존하고 있다.
Vehicle car = new Car();
Vehicle motorBike = new MotorBike();
Driver driver = new Driver();
driver.driver(car);
driver.driver(motorBike);
}
}
📌여기서 꼭 Interface만 사용해야 되는 것인가?
4) 캡슐화(Encapsulation)
서로 연관있는 속성과 기능들을 하나의 캡슐(capsule)로 만들어 데이터를 외부로부터 보호하는 것
- 데이터 보호(data protection) – 외부로부터 클래스에 정의된 속성과 기능들을 보호
- 데이터 은닉(data hiding) – 내부의 동작을 감추고 외부에는 필요한 부분만 노출
캡슐화를 구현하기 위해 두 가지 방법이 있다.
4-1) 접근제어자(access modifiers)
- 클래스나 멤버들을 외부에서 접근하지 못하도록 접근을 제한하는 역할
- Public
- default
- Protected
- Private
4-2) getter/setter