๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

"OOP" ํƒœ๊ทธ๋กœ ์—ฐ๊ฒฐ๋œ 3๊ฐœ ๊ฒŒ์‹œ๋ฌผ๊ฐœ์˜ ๊ฒŒ์‹œ๋ฌผ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  ํƒœ๊ทธ ๋ณด๊ธฐ

ยท ์•ฝ 2๋ถ„

๊ฐ์ฒด#

๊ฐ์ฒด๋Š” ๋ฌธ์žํ˜•์œผ๋กœ๋œ ํ‚ค(key)์™€ ๋ชจ๋“  ์ž๋ฃŒํ˜•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’(value) ์Œ์œผ๋กœ ๊ตฌ์„ฑ๋œ ์—ฌ๋Ÿฌ ํ”„๋กœํผํ‹ฐ(property)์˜ ์ง‘ํ•ฉ์ด๋‹ค. ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์œผ๋กœ ํ•จ์ˆ˜๊ฐ€ ๋ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด ๊ฒฝ์šฐ ๋ฉ”์†Œ๋“œ(method)๋ผ๊ณ  ๋ถˆ๋ฆฐ๋‹ค.

๊ฐ์ฒด๋Š” ๊ณ ์œ ์˜ ํŒจํ‚ค์ง€์— ์ •๋ณด๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณดํ˜ธํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

JavaScript์—์„œ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์—๋Š” ํฌ๊ฒŒ 2๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค. (์ถ”๊ฐ€์ ์œผ๋กœ Object.create()๋ฅผ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.)

let obj1 = new Object(); // '๊ฐ์ฒด ์ƒ์„ฑ์ž' ๋ฌธ๋ฒ•let obj2 = {}; // '๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด' ๋ฌธ๋ฒ•

๋‘ ๋ฐฉ๋ฒ•์€ ์ฐจ์ด๊ฐ€ ์—†๋‹ค.

Object๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋‚˜ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ƒ์„ฑํ•  ๋•Œ, ์ฐจ์ด๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์ด ์ฐจ์ด์˜ ํ•ต์‹ฌ์€ ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด([[Prototype]])์— ์žˆ๋‹ค.

๊ฐ์ฒด ์ •๋ ฌ ๋ฐฉ์‹#

"ํ”„๋กœํผํ‹ฐ์—” ์ˆœ์„œ๊ฐ€ ์žˆ์„๊นŒ?"

์ •์ˆ˜ ํ”„๋กœํผํ‹ฐ๋Š” ์ž๋™์œผ๋กœ ์ •๋ ฌ๋˜๊ณ , ๊ทธ ์™ธ์˜ ํ”„๋กœํผํ‹ฐ๋Š” ๊ฐ์ฒด์— ์ถ”๊ฐ€ํ•œ ์ˆœ์„œ๋Œ€๋กœ ์ •๋ ฌ๋œ๋‹ค. ์ฐธ๊ณ 

์ฐธ๊ณ ์ž๋ฃŒ#

ยท ์•ฝ 4๋ถ„

ํ”„๋กœํผํ‹ฐ ํ”Œ๋ž˜๊ทธ#

๊ฐ์ฒด ํ”„๋กœํผํ‹ฐ๋Š” ๊ฐ’(value) ์™€ ํ•จ๊ป˜ ํ”Œ๋ž˜๊ทธ(flag) ๋ผ ๋ถˆ๋ฆฌ๋Š” ํŠน๋ณ„ํ•œ ์†์„ฑ ์„ธ๊ฐ€์ง€๋ฅผ ๊ฐ–๋Š”๋‹ค.

  • writable : true ์ด๋ฉด ๊ฐ’์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ฝ๊ธฐ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • enumerable : true ์ด๋ฉด for ... in ๋ฃจํ”„์—์„œ ์—ด๊ฑฐํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด์—ด๊ฑฐํ•  ์ˆ˜ ์—†๋‹ค.
  • configurable : true ์ด๋ฉด ํ”„๋กœํผํ‹ฐ ์‚ญ์ œ๋‚˜ ํ”Œ๋ž˜๊ทธ ์ˆ˜์ •์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ๊ทธ๋ ‡์ง€์•Š์œผ๋ฉด ํ”„๋กœํผํ‹ฐ ์‚ญ์ œ์™€ ํ”Œ๋ž˜๊ทธ ์ˆ˜์ •์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

enumerable ํ”Œ๋ž˜๊ทธ#

์—ด๊ฑฐ ๊ฐ€๋Šฅ(enumerable) ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

๋ฐ˜๋ณต ๊ฐ€๋Šฅ(iterable)์€๋น„์Šทํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ์˜๋ฏธ์ด๋‹ค.

configurable ํ”Œ๋ž˜๊ทธ#

configurable ํ”Œ๋ž˜๊ทธ๋ฅผ false ๋กœ ์„ค์ •ํ•˜๋ฉด ๋Œ์ดํ‚ฌ ๋ฐฉ๋ฒ•์ด ์—†๋‹ค.

defineProperty ๋ฅผ ์จ๋„ ๊ฐ’์„ true ๋กœ ๋˜๋Œ๋ฆด ์ˆ˜ ์—†๋‹ค.

configurable: false ๊ฐ€ ๋งŒ๋“ค์–ด๋‚ด๋Š” ๊ตฌ์ฒด์ ์ธ ์ œ์•ฝ์‚ฌํ•ญ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  • configurable ํ”Œ๋ž˜๊ทธ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์Œ
  • enumerable ํ”Œ๋ž˜๊ทธ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์Œ.
  • writable: false ์˜ ๊ฐ’์„ true ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†์Œ(true ๋ฅผ false ๋กœ ๋ณ€๊ฒฝํ•˜๋Š”๊ฒƒ์€ ๊ฐ€๋Šฅํ•จ).
  • getter / setter ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Œ(์ƒˆ๋กญ๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ๊ฐ€๋Šฅํ•จ).

์ด๋Ÿฐ ํŠน์ง•์„ ์ด์šฉํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด โ€œ์˜์›ํžˆ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š”โ€ ํ”„๋กœํผํ‹ฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

๊ด€๋ จ Object ๋ฉ”์†Œ๋“œ#

  • Object.defineProperty : ๊ฐ์ฒด์— ์ƒˆ๋กœ์šด ์†์„ฑ์„ ์ •์˜ํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•˜๊ณ  ๊ทธ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • Object.defineProperties : ๊ฐ์ฒด์— ํ•˜๋‚˜ ๋˜๋Š” ๊ทธ ์ด์ƒ์˜ ์ƒˆ๋กœ์šด ์†์„ฑ์„ ์ •์˜ํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•˜๊ณ  ๊ทธ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • Object.getOwnPropertyDescriptor : ์ฃผ์–ด์ง„ ๊ฐ์ฒด ์ž์‹ ์˜ ์†์„ฑ์— ๋Œ€ํ•œ ์†์„ฑ ์„ค๋ช…์ž(descriptor)๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • Object.getOwnPropertyDescriptors : ์ฃผ์–ด์ง„ ๊ฐ์ฒด ์ž์‹ ์˜ ๋ชจ๋“  ์†์„ฑ๋“ค์˜ ์„ค๋ช…์ž(descriptor)๋“ค์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • Object.preventExtensions(obj) : ๊ฐ์ฒด์— ์ƒˆ๋กœ์šด ํ”„๋กœํผํ‹ฐ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†๊ฒŒ ํ•œ๋‹ค.

  • Object.seal(obj) : ์ƒˆ๋กœ์šด ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€๋‚˜ ๊ธฐ์กด ํ”„๋กœํผํ‹ฐ ์‚ญ์ œ๋ฅผ ๋ง‰์•„์ค€๋‹ค. ํ”„๋กœํผํ‹ฐ ์ „์ฒด์— configurable: false๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ํšจ๊ณผ์ด๋‹ค.

  • Object.freeze(obj) : ์ƒˆ๋กœ์šด ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€๋‚˜ ๊ธฐ์กด ํ”„๋กœํผํ‹ฐ ์‚ญ์ œ, ์ˆ˜์ •์„ ๋ง‰์•„์ค€๋‹ค. ํ”„๋กœํผํ‹ฐ ์ „์ฒด์— configurable: false, writable: false๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ํšจ๊ณผ์ด๋‹ค.

  • Object.isExtensible(obj) : ์ƒˆ๋กœ์šด ํ”„๋กœํผํ‹ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒŒ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ false๋ฅผ, ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ true๋ฅผ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • Object.isSealed(obj) : ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€, ์‚ญ์ œ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ  ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ๊ฐ€ configurable: false์ด๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • Object.isFrozen(obj) : ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€, ์‚ญ์ œ, ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ  ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ๊ฐ€ configurable: false, writable: false์ด๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์ฐธ๊ณ ์ž๋ฃŒ#

ยท ์•ฝ 9๋ถ„

class ์ž‘์„ฑ ์‹œ์— TypeScript์˜ ํด๋ž˜์Šค ๋ฌธ๋ฒ•๊ณผ JavaScript์˜ ๋ฌธ๋ฒ•์„ ๋น„๊ตํ•ด๋ณด์ž.

JS ํด๋ž˜์Šค ๋ฌธ๋ฒ•#

JS์—์„œ ํด๋ž˜์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•œ๋‹ค.

class MyClass {  publicProp = 'value'; // public ํ”„๋กœํผํ‹ฐ  #privateProp = 'value'; // private ํ”„๋กœํผํ‹ฐ. ES2019 ๋ถ€ํ„ฐ ์ง€์›.  _protectedProp = 'value'; // protected ํ”„๋กœํผํ‹ฐ. ๊ธฐ๋Šฅ์ ์œผ๋กœ ์ง€์›ํ•˜์ง€ ์•Š์ง€๋งŒ, ๊ด€๋ก€์ ์œผ๋กœ _๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ‘œํ˜„ํ•˜๊ณ  ์•ฝ์†ํ•˜์—ฌ ์‚ฌ์šฉํ•จ.
  constructor(...) { // ์ƒ์„ฑ์ž ๋ฉ”์„œ๋“œ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์„ ๋ฐ›์•„ ํ”„๋กœํผํ‹ฐ๋ฅผ ์„ค์ •ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.    // ...  }
  static staticMethod(...) {} // static ๋ฉ”์„œ๋“œ
  publicMethod(...) {} // public ๋ฉ”์„œ๋“œ  #privateMethod(...) {} // private ๋ฉ”์„œ๋“œ
  get publicProp(...) {} // getter ๋ฉ”์„œ๋“œ  set publicProp(...) {} // setter ๋ฉ”์„œ๋“œ
  get privateProp(...) {} // getter ๋ฉ”์„œ๋“œ  set privateProp(...) {} // setter ๋ฉ”์„œ๋“œ
  get protectedProp(...) {} // getter ๋ฉ”์„œ๋“œ  set protectedProp(...) {} // setter ๋ฉ”์„œ๋“œ}

ํด๋ž˜์Šค ์ƒ์†#

JS์—์„œ๋„ ํด๋ž˜์Šค ์ƒ์†์„ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๊ธฐ์กด ํด๋ž˜์Šค๋ฅผ ํ™•์žฅํ•˜์—ฌ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ• ์ˆ˜์žˆ๋‹ค.

class Animal {    constructor(name) {        this.speed = 0;        this.name = name;    }    run(speed) {        this.speed = speed;        alert(`${this.name} ์€/๋Š” ์†๋„ ${this.speed}๋กœ ๋‹ฌ๋ฆฝ๋‹ˆ๋‹ค.`);    }    stop() {        this.speed = 0;        alert(`${this.name} ์ด/๊ฐ€ ๋ฉˆ์ท„์Šต๋‹ˆ๋‹ค.`);    }}
let animal = new Animal('๋™๋ฌผ');
class Rabbit extends Animal {    hide() {        alert(`${this.name} ์ด/๊ฐ€ ์ˆจ์—ˆ์Šต๋‹ˆ๋‹ค!`);    }}
let rabbit = new Rabbit('ํฐ ํ† ๋ผ');
rabbit.run(5); // ํฐ ํ† ๋ผ ์€/๋Š” ์†๋„ 5๋กœ ๋‹ฌ๋ฆฝ๋‹ˆ๋‹ค.rabbit.hide(); // ํฐ ํ† ๋ผ ์ด/๊ฐ€ ์ˆจ์—ˆ์Šต๋‹ˆ๋‹ค!

ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ด๋‹

ํด๋ž˜์Šค Rabbit์œผ๋กœ ๋งŒ๋“  ๊ฐ์ฒด๋Š” rabbit.hide()์™€ ๊ฐ™์€ Rabbit์— ์ •์˜๋œ ๋ฉ”์„œ๋“œ์—๋„ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ณ , rabbit.run()๊ณผ ๊ฐ™์€ Animal์— ์ •์˜๋œ ๋ฉ”์„œ๋“œ์—๋„ ์ ‘๊ทผํ• ์ˆ˜์žˆ๋‹ค.

extends ํ‚ค์›Œ๋“œ๋Š” ์ด๋ ‡๊ฒŒ ํ”„๋กœํ† ํƒ€์ž… ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜์—ฌ, ๊ฐ์ฒด rabbit -> Rabbit.prototype -> Animal.prototype ์ˆœ์œผ๋กœ ๋ฉ”์†Œ๋“œ๋ฅผ ์ฐพ์•„์„œ ์‹คํ–‰ํ•œ๋‹ค.

์ ‘๊ทผ ์ œ์–ด์ž(Access Modifier)#

๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ๋Š” ์ ‘๊ทผ ์ œ์–ด์ž๋ฅผ ํ™œ์šฉํ•ด ๋‚ด๋ถ€ ์ธํ„ฐํŽ˜์ด์Šค์™€ ์™ธ๋ถ€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌ๋ถ„ํ•˜์—ฌ ์บก์Šํ™”ํ•œ๋‹ค.

  • public : ์–ด๋””์„œ๋“ ์ง€ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์™ธ๋ถ€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌ์„ฑํ•œ๋‹ค.
  • protected : ํด๋ž˜์Šค ์ž์‹ ๊ณผ ์ž์† ํด๋ž˜์Šค์—์„œ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‚ด๋ถ€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌ์„ฑํ•œ๋‹ค.
  • private : ํด๋ž˜์Šค ์ž์‹ ์—์„œ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‚ด๋ถ€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌ์„ฑํ•œ๋‹ค.

JS์—์„œ๋Š” public, protected ์— ๋Œ€ํ•œ ๋ฌธ๋ฒ•์  ์ง€์›์ด ์—†์œผ๋ฉฐ, ๊ด€์Šต์ ์œผ๋กœ _ ์ ‘๋‘์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ protected ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

private ์†์„ฑ์€ ES2019๋ถ€ํ„ฐ ์ง€์›ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

static#

์ •์  ํ”„๋กœํผํ‹ฐ์™€ ๋ฉ”์„œ๋“œ๋Š” ์–ด๋–ค ํŠน์ •ํ•œ ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ํด๋ž˜์Šค์— ์†ํ•œ ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ ์žํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

์ •์  ๋ฉค๋ฒ„๋Š” ์ƒ์†๋œ๋‹ค.

class Article {    constructor(title, date) {        this.title = title;        this.date = date;    }
    static createTodays() {        // this๋Š” Article์ž…๋‹ˆ๋‹ค.        return new this("Today's digest", new Date());    }}
let article = Article.createTodays();
alert(article.title); // Today's digest

TS ํด๋ž˜์Šค ๋ฌธ๋ฒ•#

TS๋Š” JS์˜ ๋ชจ๋“  ํด๋ž˜์Šค ๋ฌธ๋ฒ•์„ ์ง€์›ํ•˜๋ฉฐ, ๊ทธ์— ๋”ํ•ด์„œ ๋ช‡ ๊ฐ€์ง€ ๋ฌธ๋ฒ•์ ์ธ ์ง€์›์„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค. ํ•˜์ง€๋งŒ ๋ชจ๋“  ๋ฌธ๋ฒ•์€ ์ปดํŒŒ์ผ ํƒ€์ž„์— ๋Œ€ํ•ด์„œ๋งŒ ์ ์šฉ๋˜๊ณ , ๋Ÿฐํƒ€์ž„์—๋Š” ๊ฒฐ๊ตญ JS๊ฐ€์ง€์›ํ•˜๋Š” ๊ธฐ๋Šฅ๋งŒ์„ ์‚ฌ์šฉํ•ด ๋™์ž‘ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์ž.

๋‹ค์Œ์€ JS์—์„œ ์ง€์›ํ•˜์ง€ ์•Š์ง€๋งŒ, TS์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” Class์™€ ๊ด€๋ จ๋œ ๊ธฐ๋Šฅ๋“ค์ด๋‹ค.

readonly#

ํ•„๋“œ์—๋Š” readonly ์ œ์–ด์ž๋ฅผ ์ ‘๋‘์‚ฌ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€์•„๋‹Œ ๊ณณ์—์„œ ํ• ๋‹น์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

class Greeter {    readonly name: string = 'world';
    constructor(otherName?: string) {        if (otherName !== undefined) {            this.name = otherName;        }    }
    err() {        this.name = 'not ok';        // Cannot assign to 'name' because it is a read-only property.    }}const g = new Greeter();g.name = 'also not ok';// Cannot assign to 'name' because it is a read-only property.

overload#

JS๋Š” ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ฐฏ์ˆ˜์™€ ์ž๋ฃŒํ˜•์ด ์ž์œ ๋กญ๊ธฐ ๋•Œ๋ฌธ์—, ์˜ค๋ฒ„๋กœ๋“œ์— ๋Œ€ํ•œ ๊ฐœ๋…์ด์‚ฌ์‹ค์ƒ ์—†๋‹ค. (๋‹จ์ง€, ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์กฐ๊ฑด์— ๋”ฐ๋ฅธ ๋ถ„๊ธฐ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ์ •๋„)

TS์—์„œ๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜์— ๋Œ€ํ•ด ๊ตฌ์ฒด์ ์œผ๋กœ ์˜ค๋ฒ„๋กœ๋“œ signature๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

class Point {    // Overloads    constructor(x: number, y: string);    constructor(s: string);    constructor(xs: any, y?: any) {        // TBD    }}
class Util {    // Overloads    len(s: string): number;    len(arr: any[]): number;    len(x: any) {        return x.length;    }}

override#

TypeScript์—์„œ๋Š” ํŒŒ์ƒ ํด๋ž˜์Šค๊ฐ€ ํ•ญ์ƒ ๊ธฐ๋ณธ ํด๋ž˜์Šค์˜ ํ•˜์œ„ ์œ ํ˜•์ด ๋˜๋„๋ก ํ•œ๋‹ค.

class Base {    greet() {        console.log('Hello, world!');    }}
class Derived extends Base {    greet(name?: string) {        if (name === undefined) {            super.greet();        } else {            console.log(`Hello, ${name.toUpperCase()}`);        }    }}
const d = new Derived();d.greet();d.greet('reader');

ํŒŒ์ƒ ํด๋ž˜์Šค๊ฐ€ ๊ธฐ๋ณธ ํด๋ž˜์Šค์˜ ๊ทœ์น™์„ ๋”ฐ๋ฅด๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•œ๋ฐ, ๊ธฐ๋ณธ ํด๋ž˜์Šค๊ฐ€ ํŒŒ์ƒ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

// Alias the derived instance through a base class referenceconst b: Base = d;// No problemb.greet();

๋งŒ์•ฝ ํŒŒ์ƒ ํด๋ž˜์Šค๊ฐ€ ๊ธฐ๋ณธ ํด๋ž˜์Šค๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š๋Š”๋‹ค๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

class Base {    greet() {        console.log('Hello, world!');    }}
class Derived extends Base {    // Make this parameter required    greet(name: string) {        // Property 'greet' in type 'Derived' is not assignable to the same property in base type 'Base'.        // Type '(name: string) => void' is not assignable to type '() => void'.        console.log(`Hello, ${name.toUpperCase()}`);    }}
const b: Base = new Derived();// Crashes because "name" will be undefinedb.greet();

์ ‘๊ทผ ์ œ์–ด์ž(Access Modifier)#

Member Visibility

  • public : ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ๋ฉค๋ฒ„๋Š” public์œผ๋กœ ์–ด๋””์„œ๋‚˜ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.
  • protected : ํด๋ž˜์Šค ์ž์‹ ๊ณผ ์ž์† ํด๋ž˜์Šค์—์„œ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.
  • private : protected์™€ ์œ ์‚ฌํ•˜๊ฒŒ ํด๋ž˜์Šค ์ž์‹ ์—์„œ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ž์† ํด๋ž˜์Šค์—์„œ๋„ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋‹ค.

Why No Static Classes?#

TS(JS)๋Š” Java๋‚˜ C#์—์„œ ์‚ฌ์šฉํ•˜๋Š” static class ๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. (static class๋Š” ์ธ์Šคํ„ด์Šคํ™” ํ•  ์ˆ˜ ์—†๋‹ค.)

๋”ฐ๋ผ์„œ, static class ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋ถˆํ•„์š”ํ•˜๋‹ค. ๋‹จ์ง€ ๋‹จ์ˆœ ๋ฆฌํ„ฐ๋Ÿด ๊ฐ์ฒด๋ฅผ์“ฐ๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•˜๋‹ค.

// Unnecessary "static" classclass MyStaticClass {    static doSomething() {}}
// Preferred (alternative 1)function doSomething() {}
// Preferred (alternative 2)const MyHelperObject = {    dosomething() {},};

abstract#

์•„์ง ๊ตฌํ˜„ํ•˜์ง€ ์•Š์€ ๋ฉ”์†Œ๋“œ์™€ ํ”„๋กœํผํ‹ฐ์— abstract ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. abstract ๋ฉค๋ฒ„๋ฅผ ๊ฐ€์ง„ ํด๋ž˜์Šค๋Š” ๋ฐ˜๋“œ์‹œ abstarct class ์—ฌ์•ผ ํ•œ๋‹ค.

abstract class์˜ ์—ญํ• ์€ abstract ๋ฉค๋ฒ„๋ฅผ ๊ตฌํ˜„ํ•  ์„œ๋ธŒ ํด๋ž˜์Šค์˜ ๊ธฐ์ดˆ ํด๋ž˜์Šค๊ฐ€๋˜๋Š” ๊ฒƒ์ด๋‹ค.

abstract class Base {    abstract getName(): string;
    printName() {        console.log('Hello, ' + this.getName());    }}
class Derived extends Base {    getName() {        return 'world';    }}
const d = new Derived();d.printName();

์ฐธ๊ณ ์ž๋ฃŒ#