점점 강해지고 있습니다.
[Programming] 객체지향 프로그래밍
객체 지향 프로그래밍이란?
객체란?
An Object is a class instance or an array.
자바의 창시자인 제임스 고슬링이 작성한 The java Language Specification에는 객체(object)란 클래스의 인스턴스나 배열을 말한다고 정의되어 있습니다.
클래스와 객체, 인스턴스는 다음과 같이 설명합니다.
- 클래스: 설계도
- 객체: 클래스의 인스턴스
- 인스턴스: 클래스를 바탕으로 메모리에 올라가 있는 상태
자주 빗대는 자동차를 예로 들면, 자동차의 설계도는 클래스,
자동차의 엑셀을 밟으면 앞으로. 브레이크는 멈춤. 기어를 R단에 넣으면 후진. 등등 기능적인 것을 포함한 것을 객체
마지막으로 객체를 실체화(메모리에 올라가 있는 상태)하면 인스턴스라고 합니다.
절차지향과의 비교
보통 객체지향이라고 하면 절차지향과 비교하곤 합니다.
절차지향 프로그래밍은 순서와 절차를 중심으로 두기 때문에 프로그램의 순서와 흐름을 우선시하고, 객체지향 프로그래밍은 데이터를 중심으로 두기 때문에 모듈화와 자료구조를 우선시합니다.
절차지향 프로그래밍의 스파게티 코드로 인한 유지보수의 어려움 등을 보완하기 위해 객체지향이 나왔고, Java, Python, C++, C#… 같은 현대 프로그래밍 언어 대부분이 객체지향을 지원하고 있습니다.
객체지향의 특징
객체지향은 4가지 특징이 있습니다. 모 교수님이 하신 Java is A PIE(자바는 파이다?)라는 말씀이 기억납니다(..)
- A : Abstraction(추상화)
- P : Polymorphism(다형성)
- I : Inheritance(상속)
- E : Encapsulation(캡슐화)
추상화
여러 사물들의 공통된 부분을 추출하여 정의하는 것입니다. 예를 들어 호랑이와 토끼는 같은 동물로서 뛸 수 있고, 숨쉴 수 있겠죠. 이런 공통적인 기능을 추출하여 Animal로 정의했습니다.
추상화를 구현하기 위해서는 인터페이스나 추상 클래스로 구현할 수 있습니다. 이처럼 객체의 공통적인 속성과 기능을 추출하여 정의하는것을 추상화라고 합니다
public interface Animal{
void run();
void breathe();
}
public class Tiger implements Animal {
@Override // Animal 인터페이스 내의 메서드를 무조건 구현해야 함
void run() {
System.out.println("호랑이가 달린다");
}
@Override
void breathe() {
System.out.println("호랑이가 숨쉰다");
}
}
public class Rabbit implements Animal {
@Override // Animal 인터페이스 내의 메서드를 무조건 구현해야 함
void run() {
System.out.println("토끼가 달린다");
}
@Override
void breathe() {
System.out.println("토끼가 숨쉰다");
}
}
다형성
어떤 객체의 속성이나 기능이 상황에 따라 여러 가지 형태를 가질 수 있는 성질을 의미합니다. Tiger와 Rabbit은 둘 다 동물이기 때문에 Animal이라는 형태로 변경할 수 있습니다.
class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public void run() {
System.out.println(this.name+"가 뛴다.");
}
public void breathe() {
System.out.println(this.name+"가 숨쉰다.");
}
}
class Tiger extends Animal {
public Tiger(String name) {
super(name);
}
}
class Rabbit extends Animal {
public Rabbit(String name) {
super(name);
}
}
public class Main {
public static void main(String[] args) {
Animal ani1 = new Tiger("호랭이");
Animal ani2 = new Rabbit("토깽이");
ani1.run();
ani2.breathe();
}
}
결과
호랭이가 뛴다.
토꺵이가 숨쉰다.
상속
기존 클래스를 재활용하여 새로운 클래스를 작성하는 요소입니다. 클래스들 간 공유하는 속성과 기능들을 반복적으로 정의할 필요 없이 한 번만 정의해두고 간편하게 재사용할 수 있습니다.
class Animal {
public void run() {
System.out.println("뛴다.");
}
}
class Tiger extends Animal {}
public class 추상화와상속 {
public static void main(String[] args) {
Tiger ani1 = new Tiger("호랭이");
ani1.run();
}
}
결과
호랭이가 뛴다.
캡슐화
서로 연관있는 속성과 기능들을 하나의 캡슐(capsule)로 만들어 데이터를 외부로부터 보호하는 것입니다.
자바 객체 지향 프로그래밍에서 캡슐화를 구현하기 위한 방법은 접근제어자(access modifiers)를 활용하는 방법, getter/setter를 활용하는 방법이 있습니다.
접근 제어자는 클래스의 내부의 멤버들에 사용되어 해당 클래스나 멤버들을 외부에서 접근하지 못하도록 접근을 제한하는 역할을 합니다.
자바에는 public
, default
, protected
, private
총 4가지 종류의 접근 제어자가 있습니다.
접근 제어자
접근 제어자 | 클래스 내 | 패키지 내 | 다른 패키지의 하위 클래스 | 패키지 외 | 설명 |
---|---|---|---|---|---|
private | O | X | X | X | 동일 클래스 내에서만 접근 가능 |
deafult | O | O | X | X | 동일 패키지 내에서만 접근 가능 |
protected | O | O | O | X | 동일 패키지 + 다른 패키지의 하위 클래스에서 접근 가능 |
public | O | O | O | O | 접근 제한 없음 |
getter/setter
예제를 보면, name 속성이 private
접근 제어자로 선언되어 있고, getter/setter
메서드의 접근제어자만이 public
으로 열려있습니다. 따라서 선택적으로 외부에 접근을 허용할 속성과 그렇지 않을 속성을 getter/setter
메서드를 통해 설정해줄 수 있습니다.
class Animal {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
마무리
객체지향 언어라도 순서에 중요시 둔다면 절차지향 프로그래밍이라고 할 수 있습니다. 객체의 재사용성을 중요하게 생각하고 프로그래밍을 한다는 마음가짐을 가져야 할 것 같습니다.
Reference
https://brownbears.tistory.com/407
https://blog.naver.com/atalanta16/220249264429
https://www.codestates.com/blog/content/%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8A%B9%EC%A7%95