객체지향이란?
서로 관련 있는 데이터와 함수를 객체(하나의 역할을 수행하는 메소드와 변수의 묶음)로 정의해서 서로 상호작용할 수 있도록 프로그래밍 해나가는 것을 말한다. 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다.
장점
객체지향을 사용하면 중복되는 관련 객체를 재사용할 수 있어 코드의 중복을 어느 정도 줄일 수 있고 관련 있는 객체들의 역할 분담을 좀 더 확실하게 할 수 있어서 가독성이 높아질 수 있다.
- 생산성을 높여준다.
- 유지 보수 및 확장성이 높다.
참고-위키백과 참고-나무위키
객체지향 요소
캡슐화(Encapsulation)
- 서로 연관되어 있는 데이터와 함수들을 캡슐화하는 것을 말한다.
정보 은닉(Infomation Hiding)
- 프로그램의 세부 구현을 외부로 드러나지 않도록 특정 모듈 내부로 감추는 것이다.
- 서로 연관 있는 데이터와 함수들을 오브젝트 안에 담아두고 외부에서 보일 필요가 없는 세부 데이터를 숨겨 높음으로 외부에서 내부 데이터를 변경할 수 없도록 할 수 있다.
- 일반적으로 세 종류의 접근 제한이 사용된다.
constructor
- class를 가지고 instance(object)를 만들 때 항상 호출되는 함수로 데이터를 담아 호출할 수 있다.
- static 이란 키워드를 사용해서 object를 만드는 함수를 제공한다면 private constructor로 설정해두어 static method를 사용할 수 있도록 권장한다.
public
- 클래스의 외부에서 사용 가능하도록 노출시키는 것이다.
- 외부에서 데이터를 확인 또는 변경할 수 있다.
- class 안에서 변수나 함수에 따로 키워드를 사용하지 않으면 기본적으로 public 상태이다.
private
- 클래스의 내부에서만 사용되며 외부로 노출되지 않는다.
- 외부에서 데이터를 확인 또는 변경할 수 있다.
protected
- 다른 클래스에게는 노출되지 않지만, 상속받은 자식 클래스에게는 노출되는 것이다.
- 외부에서 접근할 수 없고 상속받은 class만이 접근이 가능하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
class Animal {
private emotion: string = '';
private energy: number = 0;
constructor(
private animalType: string,
private name: string,
private gender: string
) {
this.animalType = animalType;
this.name = name;
this.gender = gender;
}
play() {
this.emotion = 'happy';
}
eat(food: number) {
this.energy = food;
}
}
const dog = new Animal('dog', 'sam', 'male');
const cat = new Animal('cat', 'jang', 'female');
|
추상화
- 내부의 복잡한 기능 private 키워드를 사용해 외부에서 보이지 않도록 함으로서 외부에서 보이는 인터페이스(함수)만을 통해 내부 기능을 이해하지 않아도 사용할 수 있다.
예를 들어, eat
, play
함수를 사용하면서 외부에서는 에너지나 감정이 변화하는 함수를 이해하지 않아도 사용할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| class Animal {
private emotion: string = '';
private energy: number = 0;
constructor(
private animalType: string,
private name: string,
private gender: string
) {
this.animalType = animalType;
this.name = name;
this.gender = gender;
}
private energyUp (energy: number) {
this.energy = energy;
}
private energyDown () {
this.energy -=- 1;
}
private happyEmotion () {
this.energyDown();
this.emotion = 'happy';
}
play() {
this.happyEmotion();
}
eat(food: number) {
this.energyUp(food);
this.happyEmotion();
}
}
const dog = new Animal('dog', 'sam', 'male');
dog.eat();
dog.play();
|
상속
- 상속을 사용하여 코드의 재사용성을 높일 수 있다.
extends
- extends라는 키워드를 사용하여 class를 상속받을 수 있다.
- 상속을 할 때 constructor가 private일 경우 상속이 되지 않는다. public 또는 자식 클래스에서 접근이 가능하도록 protected 키워드를 사용해야 한다.
- 자식 클래스가 부모 클래스의 함수를 이용하고 싶다면 super 키워드로 접근할 수 있다.
- 자식 클래스에서
constructor
는 반드시 super
를 호출해야 하며 부모 클래스에서 필요한 데이터를 super를 이용해 전달해 주어야 한다.
상속의 단점: 타입스크립트에서 상속은 두가지 이상 상속받을 수 없으며 부모클래스의 변화가 있을 경우 자식 클래스도 영향을 미치는 단점이 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| class Animal {
private emotion: string = '';
private energy: number = 0;
constructor(
private animalType: string,
private name: string,
private gender: string
) {
this.animalType = animalType;
this.name = name;
this.gender = gender;
}
private energyUp (energy: number) {
this.energy = energy;
}
private energyDown () {
this.energy -= 1;
}
private happyEmotion () {
this.emotion = 'happy';
}
play() {
this.happyEmotion();
}
eat(food: number) {
this.energyUp(food);
this.happyEmotion();
}
}
class Dog extends Animal {
constructor(animalType, name, gender) {
super(animalType, name, gender)
}
barking() {
super.energyDown();
return 'wang wang';
}
}
const seryDog = new Dog('dog', 'sery', 'female');
seryDog.barking();
|
다형성
- 상속을 통해서 만들어진 자식 클래스들의 종류와 상관없이 부모 클래스에 정의된 함수를 호출할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
| class Animal {
private emotion: string = '';
private energy: number = 0;
constructor(
private animalType: string,
private name: string,
private gender: string
) {
this.animalType = animalType;
this.name = name;
this.gender = gender;
}
private energyUp (energy: number) {
this.energy = energy;
}
private energyDown () {
this.energy -=- 1;
}
private happyEmotion () {
this.emotion = 'happy';
}
play() {
this.energyDown();
this.happyEmotion();
}
eat(food: number) {
this.energyUp(food);
this.happyEmotion();
}
}
class Dog extends Animal {
constructor(animalType, name, gender) {
super(animalType, name, gender)
}
...
barking() {
super.energyDown();
return 'wang wang';
}
...
}
class Cat extends Animal {
constructor(animalType, name, gender) {
super(animalType, name, gender)
}
...
play() {
super.play();
}
...
}
const seryDog = new Dog('dog', 'sery', 'female');
seryDog.barking();
|
static
- 변수나 함수에 static이라는 키워드를 사용하면 class level로 지정된고 static이 사용하지 않으면 object level이다.
- class level은 class와 연결되어 있기 때문에 instance마다 만들어지거나 생성되지 않는다.
- object level은 this를 사용해 접근할 수 있고 class level을 사용할 때 class 이름으로 접근할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| class Animal {
static private emotion: string = '';
static private energy: number = 0;
constructor(
private animalType: string,
private name: string,
private gender: string
) {
this.animalType = animalType;
this.name = name;
this.gender = gender;
}
static makeAnimal (animalType: string, name: string, gender: string) {
return new Animal(animalType, name, gender)
}
private energyUp (energy: number) {
Animal.energy = energy;
}
private energyDown () {
Animal.energy -=- 1;
}
private happyEmotion () {
Amimal.emotion = 'happy';
}
play() {
this.happyEmotion();
}
eat(food: number) {
this.energyUp(food);
this.happyEmotion();
}
}
const dog = Animal.makeAnimal('dog', 'sery', 'female');
|
getter 와 setter
- getter와 setter를 사용하면 조금 더 다양한 연산을 할 수 있으며, 전달된 인자가 정확한지에 대해서 유요성 검사를 할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| class User {
constructor(private name: string, private age: number) {
this.name = name;
this.age = age;
}
get userInfo(): string {
return `name: ${this.name} , age: ${this.age}`
}
get age(): number {
return this.age;
}
set age(num: number) {
if (num < 0) {
throw Error('error')
}
this.age = num;
}
}
const user = new User('sara', 30);
console.log(user.userInfo) // name: sara , age: 30
user.age = 20;
console.log(user.age) // 20
|
interface
- class와 상호작용하기 위한 규약을 정의하는 것이다.
- interface를 사용할 때 implements라는 키워드랄 사용해서 class를 구현한다.
- interface로 정의한 규약을 class로 구현해야한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| type IOS = {
serialNumber: string
}
interface PhoneIOS {
makePhone(serialNumber: string):IOS
}
class Phone implements PhoneIOS {
constroctor(private serialNumber: string) {
this.serialNumber = serialNumber
}
makePhone(serialNumber: string):IOS {
return { serialNumber: string }
}
}
|
composition
- 각각의 기능을 클래스로 만들어두어 필요한 기능을 외부에서 주입받아 가져다 쓰는 것을 말한다.
- 클래스 간의 상호작용을 하는 경우 interface를 통해 상호작용하는 것이 좋다.
abstract class
- 상속 클래스를 이용할 때 특정 기능만 자식 클래스에서 달라진다면 Abstact class를 만들어 볼 수 있다.
- 클래스 앞에 abstract라는 키워드를 사용하면 해당 클래스로 자체 오브젝트를 생성할 수 없다.