반응형
이번 편의 핵심은 사물과 물체들을 class로 정리할 수 있는 눈을 기르는 능력을 갖는 것이다. 강의가 끝나고 어떻게 저것들을 class로 만들 수 있을지 생각해보라. 또한 쇼핑몰 만들 때 or 수강신청 프로그램을 만들 때 어떻게 class로 잘 정리할 수 있을까를 생각해보자.
Class 와 Object
- class를 이용해서 상속과 다양성이 일어날 수 있는데 이런 모든 것들이 가능한 것이 바로 객체지향 언어이다.
e.g.) 캡슐화, 상속, 다양성 등 - person 이라는 class 안에는 name과 age 라는 속성이 있고, speak() 말하는 function이 들어있다.
- class 안에는 이름과 나이 같은 속성(field)가 들어있고, 말하는 행동(method)가 들어있다.
- class는 조금 더 연관이 있는 데이터들을 묶어 놓은 fields와 metohds가 종합적으로 묶여있는 것을 말한다.
- 관련이 있는 변수나 함수들을 묶어 놓은 것들을 class라고 하고, classs 안에서도 내부적으로 보여지는 변수와 밖에서 보일 수 있는 변수들을 나누어어서 이런 것들을 '인큐베이션 캡슐화'라고 한다.
- data class: class 안에 methods는 들어있지 않고 data만 들어있는 것
- 프로그래밍 할 때도 사물과 물체들을 class로 / object로 정해서 프로그래밍 하는 것이 조금 더 자연스럽고 유연하다.
- 객체지향 언어로 프로그래밍을잘하는 개발자 = 풀어야 되는 문제나 구현 해야 되는 기능을 객체로 잘 정의해서 만들 수 있는 개발자
class person{
name; // field
age; // field
speak(); // method
}
Class
- template (청사진)
- declare once
- no date in
- 붕어빵을 만들 수 있는 틀
- class 자체에는 date 가 들엉 있지 않고, 틀만 template만 정해 놓는 것이다.
- 이런 class 에는 이런 date 만 들어올 수 있어 라고만 정의를 해놓는 것이다.
- 한 번만 선언한다.
object
- instance of a class
- created many times
- data in
- 이 class를 이용해서 실제로 data를 넣어서 만드는 것이 바로 object 이다.
- class를 이용해서 새로운 instancce를 생성하면 object가 되는 것이다.
- object는 class를 이용해서 굉장히 많이 만들 수 있다.
- class는 정의만 한 것이여서 실제로 메모리에 올라가지는 않지만
- 이렇게 실제로 데이터를 넣으면 이제 object는 메모리에도 올라가게 된다.
- E.G.) 우리가 붕어빵이라는 class를 이용해서 (팥, 크림, 피자)라는 데이터를 붕어빵에 넣으면 붕어빵 자체는 object이고, 이 붕어빵을 만들기 위해 우리가 정의한 붕어빵의 틀은 class가 된다.
1. class 선언
class는 template에 속하고, 이 template를 이용해서 실제로 data를 넣어서 만드는 것이 object이다.
E.G.) 붕어빵 틀이 class이고 크림, 팥, 피자 같은 data를 넣어서 만드는 것이 object이다.
'use strict';
// Object-oriented programming
// class: template
// object: instance of a class
// JavaScript classes
// - introduced in ES6 // class가 도입되기 전에는 이 class를 정의하지 않고 바로 object를 만들 수 있었다.
// - syntactical sugar over prototype-based inheritance 문법상으로 달달한 각자의 편리함을 제공하는 것을 의미한다.
// 기존에 존재하던 prototype을 기반으로, 그 위에 우리가 좀 간편하게 쓸 수 있도록 문법만 class가 추가된 것이다.
// 1. Classs declarations
class Person { // class라는 키워드를 이용해서 Person이라는 class를 만들고
// constructor ↓ 이 생성자를 이용해서 object를 만들 때 필요한 데이터를 전달한다.
constructor(name, age) {
//fields ↓
this.name = name; // 전달받은 데이터를 이 class에 존재하는 2가지 name 과 age 에 전달된 데이터를 할당해주는 것이다.
this.age = age;
}
//methods ↓
speak() {
console.log(`${this.name}: hello!`); // 단순히 this.name을 출력하면서 hello! 이렇게 인사하는 speak이다.
}
}
// Object 생성 -잘 정리한 class를 이용해서 ellie를 만들어보자.
//새로운 object를 만들 때는 new라는 키워드를 쓴다.
const ellie = new Person('ellie', 20); // 새로운 object 생성
console.log(ellie.name); // console.log 로 잘 출력되는지 확인이 가능하다.
console.log(ellie.age);
ellie.speak(); // 말하는 methods 인 speak 이렇게 함수 호출이 가능하다
// 결과는 ellie: hello!
// this라는 것은 생성된 object.name 이렇게 하기 때문에 ellie의 이름이 출력되는 것이다.
2. Getter and Setters
- C 언어는 Procedure (특정한 로직을 처리하기만 하고 결과 값을 반환하지 않는 것 / 함수를 불러서 함수를 호출해서 실행하는 프로그램)
- 자바는 Object oriented program 객체 지향 언어 ( object 가 서로 interaction 하면서 돌아가는 application을 만들 때 사용한다)
- 인캡슐레이션(캡슐화) - 우리가 자주가는 커피 vending machine => class
자판기는 커피가 있다. 자판기 커피 갯수가 있다고 하자 => integer(정수) number of coffee
커피머신으로 동전을 넣고 커피를 뽑는다.
coffee machine 에는 property가 number of coffee / methods는 2개 put coin & make coffee - number of coffee 가 integer인데 -1 이 가능할까? 안된다. 그래서 우리가 getter 와 setter를 쓰는 것이다.
- 사용자가 -원이라고 설정하면 안되니까 우리는 setter에서 0으로 만들어 주는 것이다.
- 다른 사람이 nuber of coffee 를 설정하는 것은 좋지 않다. 그래서 이 number of coffee 라는 property를 private으로 만드는 것이다.
- 즉 우리가 작성한 class를 옆에 있는 동료가 바보같이 잘못 사용해도 우리가 조금 더 방어적인 자세로 만들 수 있ㄷ도록 해주는 것이 '게터와 세터'이다.
// 2. Getter and setters
class User {
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
// user의 age가 -1 일아는 것은 말이 안되기 때문에, get 키워드를 이용해서 값을 return
// 사용자가 get age를 호출하게 되면 우리는 this.age를 return 해야한다.
get age() {
return this._age;
}
// set 키워드를 이용해서 값을 설정할 수 있다.
//단, set은 값을 설정해야 해서 value를 받아와야한다.
set age(value) {
// if (value < 0) {
// throw Error(`age can not be negative`);
// }
this._age = value < 0 ? 0 : value; // 새로운 value를 받으면 우리가 this.age를 value로 설정하게 된다. value 가 -라면 0을 쓰고 아니면 지정된 value를 쓰겠다.
}
}
const user1 = new User('Steve', 'Job', -1);
console.log(user1.age);
+ 이해를 위한 영상 댓글
class 내에 getter 와 setter 가 specifically define 되어있다면, 그 define 되어있는 property 에 한해서 accessor로 작용합니다. 그래서 위에 예제에서 age 에 대한 getter / setter 가 정확하게 define이 되어있기 때문에, 이제 저 "User" object에서의 age를 access 하려고하면 자동으로 JS가 getter / setter를 call 합니다.
그래서 this.age = age; 에서 'this.age =' 는 set age(value)를 call 합니다. 그러면 이제 여기 set age()을 보시면 set age(value){ this.age = value; } set age가 처음에 호출되고 function body를 execute할때, this.age = value; 여기서 "this.age = " 는 다시 set age(value)를 호출하고, 다시 호출된 set age 에서 "this.age = "는 또 다시 set age(value)를 호출하고.. infinite recursion이 되서 callstack overflow 에러가 발생하죠. 그래서 나온 방법이 private property convention을 이용해서 getter 와 setter 안에 따로 age를 다른 이름으로 사용하자고 해서 _age로 define해줍니다.
set age(value){ this._age = value; } 그러면 이제 다시 constructor 로 돌아가서, this.age = age; 이 실행될때 "this.age = "는 set age()를 호출하고, set age()의 body에서보면 실제로는 age가 아니라 _age 라는 또 다른 이름의 변수에 저장합니다. 여기서 _age는 setter 가 define되어있지 않기 때문에 바로 메모리에 _age의 값을 저장합니다. 실제로는 _age라는 변수가 저장된 것이기 때문에, User object에서 age가 아닌 _age도 직접 access해보면 age랑 같은 값인 것을 볼 수 있습니다. const user1 = new User('Java', 'Script', 10); console.log(user1.age); console.log(user1._age); 하면 둘다 같은 10이 나옵니다.
실제로는 age가 아니라 _age에 저장되었는데 왜 user1.age 도 10이 나오냐? 위에서도 설명했듯이 자동으로 getter를 호출하기때문에 getter에서 우리가 _age 값을 return하기로 정의를 바꾸어 주었기때문에 user1.age 도 10을 리턴하는 것입니다.
3. Public & Private
너무 최근에 추가된 것이라서 그냥 알고만 있어라.
// 3. Fields (public, private)
// Too soon! 너무 최근에 추가되었다.
// https:// 이거는 엘리노트 복붙
class Experiment {
publicField = 2; // public => 외부에서 접근이 가능하다
#privateField = 0; // #을 붙이면 class 내부에서만 값이 보여지고 접근이 되고 값이 변경이 가능하지만 클래스 외부에서는 이 값을 읽을 수도 변경할 수도 없다.
}
const experiment = new Experiment();
console.log(experiment.publicField); // 결과 2
console.log(experiment.privateField); // 결과 undefined
4. Static
너무 최근에 추가된 것이라서 그냥 알고만 있어라2
class 안에 있는 fields와 methods 들은 새로운 object를 만들 때 그대로 복제 되어서 값만 우리가 지정된 값으로 변경이 되어서 만들어 지는데, 간혹 object, data와 상관없이 class가 가지고 있는 고유한 값과 이런 data와 상관없이 동일하게 반복적으로 사용되어지는 methods가 있을 수 있다. 그런 것들을 이렇게 static이라는 키워드를 이용해서 붙이면 object에 상관없이 class 자체에 연결되어 있다.
// 4. Static properties and methods
// Too soon! 이것 또한 너무 최근에 추가되었다.
class Article {
static publiser = 'Dream Coding';
constructor(articleNumber) {
this.articleNumber = articleNumber;
}
static printPubliser() {
console.log(Article.publiser);
}
}
const article1 = new Article(1); // Article 1과 2를 object를 만들게 되면, static 없이 우리가 object를 이용해서 publisher를 출력할 수 있었을 것이다.
const article2 = new Article(2); // 그런데 결과가 undefined 가 뜬다. 그 말은 이 object 안에 publiser 는 몰라 값이 지정되지 않았어 라고 알 수 있다.
console.log(Article.publiser); // static은 object 마다 할당 되어 지는 것이 아니라 article 이라는 class 자체에 붙어있기 때문에 여기 class를 Article 로 바꾸니까 Dream Coding 이 출력된다.
Article.printPubliser(); // Static 함수를 호출 할 때도 class 이름을 이용해서 printPubliser 라고 호출하면 출력이 된다.
5. 상속 & 다양성
- 삼각형, 직사각형의 공통점은 넓이를 구할 수 있다는 것이다.
- 그래서 class shape 활용이 가능하다. 이것은 재사용이 가능하기 때문에 유지 보수하기가 쉽다. 공통적인 shape에 와서 수정하면 된다.
- 연장한다는 키워드(extends)만 이용해도 바로 shape에 있는 모든 것들이 Rectangle에 포함이 된다.
- 상속을 이용하게 되면 공통되어지는 애들을 일일이 작성하지 않아도 extends를 이용해서 동일한 것들을 재사용할 수 있다.
// 5. Inheritance
// a way for one class to extend another class.
class Shape {
constructor(width, height, color) {
this.width = width;
this.height = height;
this.color = color;
}
draw() {
console.log(`drawing ${this.color} color!`); // 여기가 뭔가 잘못됐다 하면 여기만 수정하면 다른 곳들도 다 고쳐진다.
}
getArea() {
return this.width * this.height;
}
}
class Rectangle extends Shape {}
class Triangle extends Shape {
draw() { // 여기서 위에 쓴 draw를 overwriting하면 삼각형이 출력되도록 할 수 있다.
//하지만 우리가 draw라는 method를 overwriting 했기 때문에 더이상 shape 정의된 draw가 호출되지 않는다. 둘 다 쓰려면 밑에 super.draw를 써야한다.
super.draw(); // 부모에 draw라는 함수를 호출하게 되면 이렇게 부모의 methods도 호출되고 그에 이어서 우리가 정리한 draw methods가 호출된다.
console.log('🔺');
}
getArea() {
return (this.width * this.height) / 2; // 삼격형 넓이 공식을 써야한다. 또 필요한 함수들만 재정리해서 쓰는 것 => overwriting
}
toString() { // 6번을 위해 추가한 것. 좀 더 의미있는 데이터를 만들기위해 쓴 것이다.
return `Triangle: color: ${this.color}`;
}
}
const rectangle = new Rectangle(20, 20, 'blue');
rectangle.draw();
console.log(rectangle.getArea());
const triangle = new Triangle(20, 20, 'red');
triangle.draw();
console.log(triangle.getArea());
6. instanceOf
object에 CTRL + CLICK 하면 정의된 부분으로 갈 수 있다. JS의 모든 object는 이 object를 상속한 것이다.
// 6. Class checking: instanceOf operator
// 왼쪽에 있는 object가 오른쪽에 있는 class를 이용해서 만들어진 아이인지 아닌지 확인하는 것이다.
console.log(rectangle instanceof Rectangle); // true
console.log(triangle instanceof Rectangle); // false
console.log(triangle instanceof Triangle); // true
console.log(triangle instanceof Shape); // false => true 이다. triangle은 shape를 상속했다.
console.log(triangle instanceof Object); // false => true 이다. 우리가 JS에서 만든 모든 object classs들은 이 object를 상속한 것이다.
console.log(triangle.toString()); // 우리는 어떤 object 던지 공통적으로 존재하는 methods를 쓸 수 있다.
// 이것의 결과는 [object Object] 인데 5번에 toString() 이것을 추가함으로써 의미있는 데이터로 만들 수 있다.
let obj = { value: 5 };
function change(value) {
value.value = 7;
}
change(obj);
console.log(obj);
#자바스크리트 object
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference
반응형
'[자기계발] > 유튜브로 코딩배우기' 카테고리의 다른 글
[드림코딩 엘리] 자바스크립트 배열 개념 & APIs 정리 (0) | 2021.08.06 |
---|---|
[드림코딩 엘리] 자바스크립트 Object를 만드는 방법, key 사용법, (0) | 2021.08.05 |
[드림코딩 엘리] 자바스크립트 Function Expression이란? (2) | 2021.08.01 |
[드림코딩 엘리] function 사용법 코딩 return이란? (0) | 2021.07.30 |
[드림코딩 엘리] 자바스크립트 연산, 반복문. 헷갈리는 ++i, i++ 이해 / 짝수, 홀수 구하는 방법 (0) | 2021.07.25 |