<자바스크립트 객체 지향 기본기>
2. 객체 지향 프로그래밍의 4개의 기둥
📌 객체 지향 프로그래밍의 핵심 개념 4가지
추상화
캡슐화
상속
다형성
추상화
어떤 구체적인 존재를 원하는 방향으로 간략화해서 나타내는 것
→ 따라서 클래스를 설계하는 것도 모두 추상화 과정에 해당!
💡클래스의 이름, 프로퍼티와 메소드의 이름을 잘 짓는 것 중요
추상화 직접 해보기
실습
각 프로퍼티와 메소드 이름 위에 그 의미를 나타내는 간단한 주석을 직접 작성
class BankAccount {
constructor(name, money) {
// 소유주
this.holder = name;
// 잔액
this.balance = money;
}
// 입금하기
deposit(money) {
this.balance += money;
}
// 출금하기
withdraw(money) {
if (this.balance - money < 0) {
console.log('Insufficient balance');
} else {
this.balance -= money;
}
}
// 이체하기
transfer(money, anotherAccount) {
const account = anotherAccount;
if (this.balance - money < 0) {
console.log('Insufficient balance');
} else {
this.balance -= money;
account.balance += money;
}
}
}
캡슐화
객체의 특정 프로퍼티에 직접 접근하지 못하도록 막는 것
💡특정 프로퍼티에 대한 접근을 미리 정해진 메소드들을 통해서만 가능하도록 하는 것
setter 메소드 : 특정값을 설정할 때마다 파라미터로 받아와 설정할 수 있고 추가적으로 코드를 실행
getter 메소드 : 프로퍼티의 값을 구하는 함수
* getter 메소드 프로퍼티의 값을 읽는 용도로 사용 -> 파라미터를 따로 써줄 필요 없음
class User{
constructor(email, birthdate){
this.email = email;
this.birthdate= birthdate;
}
buy(item){
console.log(`${this.email} buys ${item.name}`);
}
get email(){
return this._email;
}//getter 메소드 프로퍼티의 값을 읽는 용도로 사용 -> 파라미터를 따로 써줄 필요 없음
set email(address){//setter 메소드
if(address.includes(`@`)){
this._email=address; // 만약 address 안에 at(@)이 포함된다면
//이 email에 address를 한다
}else{
throw new Error('invaild email address');
}
}//값에 대한 유효성 검사
}
const item ={
name: '스웨터',
price: 3000,
}
const user1 = new User('chris123@google.com','1992-03-21');
console.log(user1.email);
console.log(user1.birthdate);
user1.email= 'chirs robert';
• 숨기고자 하는 프로퍼티의 이름은 맨 앞에 언더바 _ 가 붙은 형식으로 써 줄 때가 많다 (하나의 관습)
1. 완벽한 캡슐화를 하는 법
JavaScript에서도 다른 방식으로 우회해서 완벽한 캡슐화를 할 수는 있음.
클로저(Closure)라고 하는 개념을 응용해서 적용
function createUser(email, birthdate) {
let _email = email;
const user = {
birthdate,
get email() {
return _email;
},
set email(address) {
if (address.includes('@')) {
_email = address;
} else {
throw new Error('invalid email address');
}
},
};
return user;
}
const user1 = createUser('chris123@google.com', '19920321');
console.log(user1.email);
-----------------------------------------------------
function createUser(email, birthdate) {
let _email = email;
const user = {
birthdate,
get email() {
return _email;
},
set email(address) {
if (address.includes('@')) {
_email = address;
} else {
throw new Error('invalid email address');
}
},
};
return user;
}
const user1 = createUser('chris123@google.com', '19920321');
console.log(user1._email); // _ 추가
//undefiend 출력됨 user1 객체의 _email 프로퍼티에 접근하려고 하면,
//user1 객체 자체 내에는 _email이라고 하는 프로퍼티가 없고,
//바깥의 _email 변수에 현재 접근할 수도 없기 때문
코드해석
createUser라고 하는 Factory function이 보인다. 이때 생성하려는 user 객체 안에 _email 프로퍼티가 있는 게 아니라,
(1) createUser 함수 안에,
(2) 그리고 user 객체 바깥에 _email이라는 변수가 있다
대신에 user 객체 안에는 _email 변수의 값을 읽고 쓸 수 있는 email이라는 getter/setter 메소드가 있다.
클로저란 자바스크립트에서 어떤 함수와 그 함수가 참조할 수 있는 값들로 이루어진 환경을 하나로 묶은 것을 의미
→ 함수가 정의된 당시에 참조할 수 있었던 변수들을 계속 참조할 수 있는 상태의 함수를 클로저라고 한다
자바스크립트에서는 클로저라는 개념으로 해당 환경을 함수와 함께 그대로 유지시켜주는 것이다
2. 메소드도 캡슐화할 수 있다
function createUser(email, birthdate) {
const _email = email;
let _point = 0;
function increasePoint() {
_point += 1;
}
const user = {
birthdate,
get email() {
return _email;
},
get point() {
return _point;
},
buy(item) {
console.log(`${this.email} buys ${item.name}`);
increasePoint();
},
};
return user;
}
const item = {
name: '스웨터',
price: 30000,
};
const user1 = createUser('chris123@google.com', '19920321');
user1.buy(item);
user1.buy(item);
user1.buy(item);
console.log(user1.point);
user1.increasePoint(); // user1 객체로 increasePoint 직접 호출 -> 에러 발생
코드해석
user1 객체에는 increasePoint라는 메소드가 없기 때문에 직접 호출하면 에러가 발생한다. increasePoint가 유저 객체 안에서 적절한 곳에 사용되어야 하고, 아무렇게나 함부로 호출해서는 안 되는 메소드라고 가정하고 이렇게 캡슐화한다
상속
하나의 객체가 다른 객체의 프로퍼티와 메소드를 물려받을 때
class User{
constructor(email, birthdate){ //super
this.email = email;
this.birthdate= birthdate;
}
buy(item){
console.log(`${this.email} buys ${item.name}`);
}
}//부모 클래스
class PremiumUser extends User {//자식 클래스
constructor(email, birthdate, level){
this.level=level;
}
streamMusicForFree(){
console.log(`Free music streaming for ${this.email}`);
}//새롭게 생겨난 부분
}//상속을 할 땐 중복코드는 제거
const item ={
name: '스웨터',
price: 30000,
}
const pUser1= new PremiumUser('chris123@google.com', '19920321');
console.log(pUser1.email);
console.log(pUser1.birthdate);
console.log(pUser1.level);
pUser1.buy(item);
pUser1.streamMusicForFree();
//코드의 재사용성이 좋아진다
→ 이대로 코드를 실행하면 에러가 발생한다
💡자식 클래스 안에서 super 생성자를 호출해야함
super
부모 클래스에 있는 생성자 함수를 의미한다 (부모의 constructor 부분)
💡자식 클래스로 객체를 만드려고 할 때는 반드시 부모 생성자 객체를 먼저 호출 해줘야한다
class User{
constructor(email, birthdate){
this.email = email;
this.birthdate= birthdate;
}
buy(item){
console.log(`${this.email} buys ${item.name}`);
}
}//부모 클래스
class PremiumUser extends User {//자식 클래스
constructor(email, birthdate, level){
super(email,birthdate);
this.level=level;
}
streamMusicForFree(){
console.log(`Free music streaming for ${this.email}`);
}//새롭게 생겨난 부분
}//상속을 할 땐 중복코드는 제거
const item ={
name: '스웨터',
price: 30000,
}
const pUser1= new PremiumUser('chris123@google.com', '19920321',3);
console.log(pUser1.email);
console.log(pUser1.birthdate);
console.log(pUser1.level);
pUser1.buy(item);
pUser1.streamMusicForFree();
//코드의 재사용성이 좋아진다
☑️실행결과
다형성
많은 형태를 갖고 있는 성질
☑️오버라이딩
자식 클래스에서 부모 클래스와 동일한 이름의 메소드를 정의하고 그 내용을 다르게 채우는 것
class User{
constructor(email, birthdate){
this.email = email;
this.birthdate= birthdate;
}
buy(item){
console.log(`${this.email} buys ${item.name}`);
}
}//부모 클래스
class PremiumUser extends User {//자식 클래스
constructor(email, birthdate, level){
super(email,birthdate);
this.level=level;
}
streamMusicForFree(){
console.log(`Free music streaming for ${this.email}`);
}
buy(item){
console.log(`${this.email} buys ${item.name} with a 5% discount`);
}
}
const item ={
name: '스웨터',
price: 30000,
}
const user1= new User('chris123@google.com', '19920321');
const user2= new User('rachel3@google.com', '19820221');
const user3= new User('brian@google.com', '19900121');
const pUser1= new PremiumUser('tommy@google.com', '19901207',3);
const pUser2= new PremiumUser('helloMike@google.com', '19990915',1);
const pUser3= new PremiumUser('alicek@google.com', '20010722',2);
const users=[user1, pUser1, user2, pUser2, user3, pUser3];
users.forEach((user)=>{
user.buy(item);
});
user1.buy(item);
pUser1.buy(item);
☑️실행결과
instacneof 연산자
💡어느 클래스로 만든 객체인지 확인하고 싶을 때 instacneof 연산자 사용
class User{
constructor(email, birthdate){
this.email = email;
this.birthdate= birthdate;
}
buy(item){
console.log(`${this.email} buys ${item.name}`);
}
}//부모 클래스
class PremiumUser extends User {//자식 클래스
constructor(email, birthdate, level){
super(email,birthdate);
this.level=level;
}
streamMusicForFree(){
console.log(`Free music streaming for ${this.email}`);
}
buy(item){
super.buy(item);//부모클래스 buy메소드 호출
this.point+=item.price*0.05;
}
}
const item ={
name: '스웨터',
price: 30000,
}
const user1= new User('chris123@google.com', '19920321');
const user2= new User('rachel3@google.com', '19820221');
const user3= new User('brian@google.com', '19900121');
const pUser1= new PremiumUser('tommy@google.com', '19901207',3);
const pUser2= new PremiumUser('helloMike@google.com', '19990915',1);
const pUser3= new PremiumUser('alicek@google.com', '20010722',2);
const users=[user1, pUser1, user2, pUser2, user3, pUser3];
users.forEach((user)=>{
console.log(user instanceof PremiumUser);
});
자식 클래스로 만든 객체는 부모 클래스로 만든 객체로도 인정된다
☑️실행결과
static 프로퍼티와 static 메소드
static 프로퍼티
static 메소드
→ 클래스에 직접적으로 딸려있는 프로퍼티와 메소드
💡즉 클래스로 객체를 만들었을 때 객체어서 활용할 프로퍼티와 메소드가 아니라 클래스 자체로 접근해서 사용할 때 !
class Math{
static PI=3.14;
static getCircleArea(radius){
return Math.PI*radius*radius;
}
}
//기존값 수정 가능
Math.PI=3.141592;
Math.getCircleArea = function(width, height){
return width * height;
}
console.log(Math.PI);
console.log(Math.getCircleArea(4,5));
console.log(Date.now());
클래스는 파일 하나당 하나씩
클래스와 메인 로직(main.js)을 파일별로 쪼개서 작성한다.
*모듈 내부의 것을 공개하고(export), 다른 모듈의 것을 가져오는(import)
실무에서는 이렇게 파일 하나당 클래스 하나를 두고 외부에 공개하는 방식을 많이 사용한다 그래야 코드를 좀더 편리하게 관리할 수 있기 때문
'🏃♀️ 대외활동 > Codeit Boost-Node.js' 카테고리의 다른 글
5주차 스터디 자바스크립트 웹 개발 기본기 (2) Web API [코드잇 부스트 백엔드 스터디 ] (1) | 2024.06.04 |
---|---|
5주차 스터디 자바스크립트 웹 개발 기본기 (1) 웹 기초 [코드잇 부스트 백엔드 스터디 ] (2) | 2024.06.04 |
5주차 스터디 자바스크립트 객체 지향 기본기 (1) [코드잇 부스트 백엔드 스터디 ] (0) | 2024.06.04 |
4주차 스터디 모던 자바스크립트 (4) [코드잇 부스트 백엔드 스터디 ] (0) | 2024.05.25 |
4주차 스터디 모던 자바스크립트 (3) [코드잇 부스트 백엔드 스터디 ] (0) | 2024.05.25 |