명령형, 절차지향적 프로그래밍
앱을 구현하기위한 데이터와 함수로 구성됨
정의된 순서대로 함수가 구동하는 프로그래밍
구현을 위해서는 모든 코드를 이해해야하여
유지보수가 어렵고 에러찾기가 어렵다.
객체지향 프로그래밍
서로 관련있는 데이터와 함수를
여러가지 오브젝트(객체)로 구성하여
프로그래밍 해나가는 것.
문제가 생기면 관련된 오브젝트만 확인하면 되고,
기능을 추가한다면 새로운 오브젝트를 만들면 되어
유지보수가 쉬워진다.
오브젝트(객체)
데이터와 함수로 구성됨
하나의 객체로써 명사로 이름을 짓는다.
오브젝트 내 데이터는 fields/properties라고 부른다.
오브젝트 내 함수는 메소드라고 부른다.
클래스와 오브젝트
클래스는 오브젝트를 만드는 일종의 템플릿
템플릿(클래스)를 이용해 만든 객체가 오브젝트
이러한 객체를 클래스의 인스턴스라고 부른다.
객체지향 프로그래밍의 원칙
캡슐화 / 추상화 / 상속 / 다형성 이 4가지를
객체지향 프로그래밍의 4원칙 이라고 부른다.
캡슐화
여러 기능들 중 서로 연관성있는 기능들을
묶는것을 "캡슐화"
eg)
감기약 캡슐에 다양한 성분의 약이 있지만
캡슐로 감싸두고, 안에 무엇이 있는지 모르고 그냥 먹는것과 같음
eg)
우리가 고양이 내부의 상태를 직접 바꿀수 없다.
고양이와 놀아줌으로써 내부 상태를 바꿀수는 있다.
이렇듯 안에 있는 것은 직접 건드리지 않고,
외부에 공개된 기능을 통해 내부의 값을 변경하는 것
그리고 어떤것을 외부에 공개하고 공개 안할지 결정하는것
이러한 일련의 행위를 "캡슐화" 라고함
키워드: public / private / protected
멤버변수의 기본 상태: public
외부에 공개하고 싶지 않을때: private
외부에서는 접근 할수없지만 상속한 자식 클래스에서는 접근할수있게 해주는것: protected
추상화
내부의 복잡한 기능을 다 이해하지 않더라도
외부에서 내부가 어떻게 구현됐는지는 상관않고
외부에서 보이는 인터페이스 만으로 이용할 수 있는 것 다시 말하면,
우리가 자동차의 원리를 몰라도 엑셀과 브레이크만 알면 운전할수 있듯이 외부에서는 내부에 어떻게 구현됐는지 신경쓰지않고 인터페이스만을 통해 함수를 이용할 수 있도록 하는 것
추상화 전
type Animal = 'dog', 'cat', 'pig';
type PetSkill = 'give me hand', 'sit down', 'high five';
class Pet {
private skills: PetSkill;
cosntructor(public kind: Animal, public name: string) {
}
training(skill: PetSkill) {
this.edu();
this.charming();
this.skills.push(skill);
}
charming() {
...
}
edu() {
...
}
}
추상화 방법1 - 정보은닉
type Animal = 'dog', 'cat', 'pig';
type PetSkill = 'give me hand', 'sit down', 'high five';
class Pet {
private skills: PetSkill;
cosntructor(public kind: Animal, public name: string) {
}
training(skill: PetSkill) {
this.edu();
this.charming();
this.skills.push(skill);
}
private charming() {
...
}
private edu() {
...
}
}
const myPuppy = new Pet('dog', 'meongu');
myPuppy.training('give me hand');
추상화 방법2 - interface
type Animal = 'dog', 'cat', 'pig';
type PetSkill = 'give me hand', 'sit down', 'high five';
interface Pet {
training(skill: PetSkill): void;
}
class FriendPet {
private skills: PetSkill;
cosntructor(public kind: Animal, public name: string) {
}
training(skill: PetSkill) {
this.edu();
this.charming();
this.skills.push(skill);
}
charming() {
...
}
edu() {
...
}
}
const myPuppy: Pet= new FriendPet('dog', 'meongu');
myPuppy.training('give me hand');
상속
상속을 이용하면 잘 정의해둔 클래스를 재사용하여 부모 클래스의 function, properties를 상속하여 새로운 클래스를 쉽게 만들어 낼 수있다.
다형성
상속을 받은 자식 클래스들은 자신이 무엇인지와 관계없이 부모 클래스의 function을 공통적으로 호출할 수 있다.
static
모든 인스턴스가 동일하게 가지는 멤버변수가 있다면 static을 붙여주자. 그러면 class레벨로 멤버변수가 변경되어, 매번 인스턴스를 만들때마다 메모리를 차지하지 않는다.
get/set
getter, setter를 활용하면
클래스 사용자는 멤버변수를 다루듯이
age를 쓸수있으면서, 내부적으로는 예외처리까지 할수있다.
이러한 큰 장점이 있어 많은 개발자들이 애용하고있다.
(어떤 개발자는 getter/setter가 몇몇 경우에 직관적이지 못하다 등의 이유로 쓰지 않는것을 권장하기도 한다.)
class Person {
private nationalAge: number;
constructor(private firstname: string, public lastname: string) {
}
get fullname(): string {
return `${this.firstname}${this.lastname}`;
}
get age(): number {
return age;
}
set age(num: number) {
if (!num || typeof num !== number) {
throw new Error('숫자를 넘기셔야지요!');
}
this.nationalAge = num;
}
}