πŸ‘¨β€πŸ’»

Typescript μ΄ν•΄ν•˜κΈ° 2편

2021-02-21   |   개발

post-img

κΉƒν—™ TIL λ ˆν¬μ— κΈ°λ‘ν–ˆλ˜ λ‚΄μš©μ„ μ •λ¦¬ν•˜μ—¬ λΈ”λ‘œκΉ…ν•©λ‹ˆλ‹€.

νƒ€μž…μŠ€ν¬λ¦½νŠΈ μ΄λ„˜ νƒ€μž…

μ΄λ„˜μ˜ κΈ°λ³Έ

μ΄λ„˜μ€ μžλ°”μŠ€ν¬λ¦½νŠΈ κ°œλ°œμžμ—κ²ŒλŠ” 정말 μƒμ†Œν•œ κ°œλ…μ΄λ‹€. μƒκΈ΄μƒˆμ™€ 처음 λ΄€μ„λ•Œμ˜ λŠλ‚Œμ€ 객체와 배열을 μ„žμ€ μƒˆλ‘œμš΄ μžλ£Œν˜• νƒ€μž…μ΄λΌλŠ” 것이닀. 근데 κ·Έ λŠλ‚Œμ΄ μ–ΌμΆ” λ§žλ‹€.

Enum은 νŠΉμ • κ°’λ“€μ˜ 집합을 μ˜λ―Έν•œλ‹€. μ‚¬μš© 방식은 μΈν„°νŽ˜μ΄μŠ€μ™€ λΉ„μŠ·ν•œλ°, enum νƒ€μž… 이름 {} ν˜•νƒœλ‘œ μ μš©ν•  수 μžˆλ‹€. νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” μˆ«μžν˜•κ³Ό λ¬Έμžν˜• μ΄λ„˜μ„ μ§€μ›ν•œλ‹€. 두 ν˜•νƒœλ₯Ό λ³΅ν•©μ μœΌλ‘œ μ‚¬μš©ν•˜λŠ” λ³΅ν•©ν˜• μ΄λ„˜μ΄ μžˆμ§€λ§Œ, 가급적이면 같은 ν˜•νƒœλ‘œ μ •μ˜ν•˜λŠ” 것이 μ’‹λ‹€.


μˆ«μžν˜• μ΄λ„˜

μˆ«μžν˜• μ΄λ„˜μ€ κΈ°λ³Έ μ΄ˆκΈ°κ°’μ΄ λ°°μ—΄μ˜ 인덱슀처럼 0이닀. 그리고 μ΄ˆκΈ°κ°’μ„ κΈ°μ€€μœΌλ‘œ 1μ”© λŠ˜μ–΄κ°„λ‹€. λ°°μ—΄κ³Όμ˜ 차이점은 μ΄ˆκΈ°κ°’μ„ κ°œλ°œμžκ°€ 지정할 수 μžˆλ‹€λŠ” 점이닀. μ‚¬μš©λ°©λ²•μ€ 객체λ₯Ό λ‹€λ£¨λŠ” 것과 λΉ„μŠ·ν•˜λ‹€.

μˆ«μžν˜• μ΄λ„˜μ€ λ¦¬λ²„μŠ€ 맡핑을 μ§€μ›ν•œλ‹€. μ΄λ„˜μ— λ“±λ‘λœ 각각의 킀와 κ°’μœΌλ‘œ μ„œλ‘œμ˜ 값을 얻을 수 μžˆλŠ” 것이닀. μˆ«μžν˜• μ΄λ„˜λ§Œ κ°€λŠ₯ν•˜λ‹€.

// up ~ left μˆœμ„œλ‘œ 1 ~ 4κ°€ μ§€μ •λœλ‹€. enum Direction { up = 1, right, down, left, } function robotWork(command: string, work: Direction): void { ... } robotWork('robot go straight', Direction.right); // reverse mapping const upValue = Direction.up; const upKey = Direction[upValue];

λ¬Έμžν˜• μ΄λ„˜

λ¬Έμžν˜• μ΄λ„˜μ€ μˆ«μžν˜• μ΄λ„˜κ³Ό μ •μ˜ν•˜κ³  μ‚¬μš©ν•˜λŠ” 방법이 λΉ„μŠ·ν•˜λ‹€. 차이점은 μˆ«μžν˜•μ˜ 경우 제일 첫 μš”μ†Œμ—κ²Œ μ΄ˆκΈ°κ°’μ„ μ§€μ •ν•˜λ©΄ μžλ™μœΌλ‘œ κ·Έ 값이 μ¦κ°€ν•˜μ—¬ λΆ€μ—¬λ˜μ§€λ§Œ, λ¬Έμžν˜• μ΄λ„˜μ€ 각 μš”μ†Œμ— λͺ…ν™•ν•œ κ°’μœΌλ‘œ μ΄ˆκΈ°ν™”κ°€ ν•„μš”ν•˜λ‹€.

enum Direction { up = "up" right = "right" down = "down" left = "left" }



νƒ€μž…μŠ€ν¬λ¦½νŠΈ 클래슀의 νƒ€μž…

기본적으둜 μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ 클래슀λ₯Ό μ •μ˜ν•˜λŠ” 것과 λΉ„μŠ·ν•˜λ‹€.

클래슀 λ‚΄λΆ€μ˜ 맴버 λ³€μˆ˜, 객체가 생성될 λ•Œ ν˜ΈμΆœλ˜λŠ” μƒμ„±μž μ»¨μŠ€νŠΈλŸ­ν„°(constructor), 그리고 νŠΉμ • λ™μž‘μ„ λ§Œλ“œλŠ” λ©”μ„œλ“œκΉŒμ§€, 클래슀λ₯Ό μ •μ˜ν•˜λŠ” λ°©λ²•μ—μ„œ νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” μžλ°”μŠ€ν¬λ¦½νŠΈμ™€ λΉ„μŠ·ν•˜λ‹€. extends ν‚€μ›Œλ“œλ‘œ 클래슀 상속을 λ°›λŠ” 것도 λ™μΌν•˜λ‹€.

class Person { // 멀버 λ³€μˆ˜ name: string; constructor(name: string) { // 멀버 λ³€μˆ˜ μ΄ˆκΈ°ν™” this.name = name; } sayHello() { console.log(`hi, i am ${this.name}`); } } class Hankyeol extends Person { constructor(name: string) { // 상속받은 μžμ‹ ν΄λž˜μŠ€μ—μ„œ // constructorλ₯Ό μ‚¬μš©ν•˜λ €λ©΄ λ°˜λ“œμ‹œ super ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•œλ‹€. // superλŠ” λΆ€λͺ¨ 클래슀의 constructorλ₯Ό ν˜ΈμΆœν•œλ‹€. super(name); } }

ν‚€μ›Œλ“œλ‘œ 멀버 λ³€μˆ˜ 곡개 λ²”μœ„ μ •ν•˜κΈ°

νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό μ‚¬μš©ν•˜λ©΄ 클래슀λ₯Ό ν†΅ν•œ 객체 생성 및 μƒμ†μ‹œμ— λΆ€λͺ¨ 클래슀의 멀버 λ³€μˆ˜, λ©”μ„œλ“œμ˜ 곡개 λ²”μœ„λ₯Ό 지정할 수 μžˆλ‹€. private, protected, publicμ΄λΌλŠ” ν‚€μ›Œλ“œλ₯Ό 멀버 λ³€μˆ˜ μ•žμ— λΆ™μ—¬ μ§€μ •ν•œλ‹€.

  • public은 단어 뜻 κ·ΈλŒ€λ‘œ 외뢀에도 λ…ΈμΆœλ˜κ³  μƒμ†μ‹œμ— μžμ‹ ν΄λž˜μŠ€μ—λ„ λ…ΈμΆœλ˜λŠ” λ²”μœ„λ₯Ό μ§€μ •ν•œλ‹€. ν‚€μ›Œλ“œ 없이 클래슀λ₯Ό 생성할 λ•Œ, public이 λ””ν΄νŠΈλΌκ³  μƒκ°ν•˜λ©΄ νŽΈν•˜λ‹€.
  • privateλŠ” κ°œμΈμ μ΄λΌλŠ” 뜻처럼, 외뢀에도 λ…ΈμΆœλ˜μ§€ μ•Šκ³  상속이 λ˜λŠ” μžμ‹ ν΄λž˜μŠ€μ—λ„ λ…ΈμΆœλ˜μ§€ μ•ŠλŠ”λ‹€. # 기호둜 μ‚¬μš©ν•  수 μžˆλ‹€. (# κΈ°ν˜ΈλŠ” μ΅œκ·Όμ— μΆ”κ°€λœ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν‘œμ€€μ΄λ‹€.)
  • protected ν‚€μ›Œλ“œλŠ” μƒμ†λ°›λŠ” ν΄λž˜μŠ€μ—λ§Œ λ…ΈμΆœλ˜λŠ” λ²”μœ„λ₯Ό μ§€μ •ν•œλ‹€. μ™ΈλΆ€μ—μ„œλŠ” μ ‘κ·Όν•  수 없도둝 λ³΄ν˜Έν•˜λŠ” μƒ˜μ΄λ‹€. constructor에 뢙이면 μ™ΈλΆ€μ—μ„œ 객체λ₯Ό μƒμ„±ν•˜μ§€ λͺ»ν•˜λ„둝 막을 수 μžˆλ‹€.
  • readonly 속성 μ—­μ‹œ μžˆλ‹€. constructor둜 멀버 λ³€μˆ˜μ— 처음 값을 ν• λ‹Ήν•œ μ΄ν›„μ—λŠ” 값을 λ³€κ²½ν•  수 μ—†λ‹€.
class Shark { protected familyMember: string; public character: string; private constructor(familyMember: string, character: string) { ... } } const babyShark = new Shark('baby', 'charm') // Error: constructor is private

멀버 λ³€μˆ˜ 지정 μƒλž΅ν•˜κΈ°

멀버 λ³€μˆ˜λ₯Ό μ§€μ •ν•˜κ³ , constructor둜 μ΄ˆκΈ°ν™” ν•΄μ£ΌλŠ” μ½”λ“œλ₯Ό 맀번 μž‘μ„±ν•˜λŠ” 것은 정말 번거둜운 일이닀. μœ„μ—μ„œ 멀버 λ³€μˆ˜ μ‚¬μš© λ²”μœ„λ₯Ό κ²°μ •ν•˜λŠ” ν‚€μ›Œλ“œλ₯Ό μ΄μš©ν•΄μ„œ νƒ€μž…μŠ€ν¬λ¦½νŠΈλ‘œ 클래슀λ₯Ό 쑰금 더 νŽΈν•˜κ²Œ μž‘μ„±ν•  수 μžˆλ‹€.

constructor ν•¨μˆ˜μ˜ μΈμžμ— λ“€μ–΄μ˜€λŠ” μΈμžμ— μ‚¬μš© λ²”μœ„μ— λŒ€ν•œ ν‚€μ›Œλ“œλ₯Ό λΆ™μ—¬μ£Όλ©΄ λœλ‹€.

class Shark { constructor(public character: string) { // public으둜 μ •μ˜ν•œ μš”μ†ŒλŠ” μžλ™μœΌλ‘œ 멀버 λ³€μˆ˜λ‘œ μΈμ‹ν•œλ‹€. // this둜 μ΄ˆκΈ°ν™” ν•˜λŠ” μ½”λ“œλ„ ν•„μš”μ—†λ‹€. } }

static, abstract ν‚€μ›Œλ“œ

class λ‚΄λΆ€μ—μ„œ static으둜 μ •μ˜λœ 멀버 λ³€μˆ˜μ™€ λ©”μ„œλ“œλŠ” μ ˆλŒ€μ μΈ 값이라고 μƒκ°ν•˜λ©΄ νŽΈν•˜λ‹€. 클래슀둜 μƒμ„±λ˜λŠ” μ–΄λ–€ 객체와도 상관없이 λ‚΄λΆ€μ—μ„œ κ³ μ •λœ 값이닀. static ν‚€μ›Œλ“œλ‘œ μ •μ˜λœ λ³€μˆ˜, λ©”μ„œλ“œλŠ” μ•žμ— μ •μ μ΄λΌλŠ” 말이 λΆ™λŠ”λ‹€. (적적 멀버 λ³€μˆ˜, 정적 λ©”μ„œλ“œ)

정적 멀버 λ³€μˆ˜μ™€ 정적 λ©”μ„œλ“œλŠ” 클래슀λͺ….λ³€μˆ˜/λ©”μ„œλ“œ ν˜•νƒœλ‘œ 클래슀 이름 μžμ²΄μ— λΆ™μ–΄μ„œ ν˜ΈμΆœν•˜κ³  μ‚¬μš©ν•œλ‹€.

class Shark { static maxAge = 150; constructor(public age: number) {} eatHuman(): string { // eatingAge λ©”μ„œλ“œλŠ” 정적 λ©”μ„œλ“œλΌ μ•„λž˜μ™€ 같이 μ‚¬μš©ν•œλ‹€. return Shark.eatingAge(this.age) ? 'yammy' : 'Hmm..'; } static eatingAge(age: number): boolean { // maxAge λ³€μˆ˜λŠ” 정적 멀버 λ³€μˆ˜λΌ '클래슀λͺ….λ³€μˆ˜'둜 ν˜ΈμΆœν•œλ‹€. return Shark.maxAge <= 50; } }

abstract ν‚€μ›Œλ“œκ°€ 뢙은 ν΄λž˜μŠ€λŠ” new ν‚€μ›Œλ“œλ‘œ 객체λ₯Ό 생성할 수 μ—†λ‹€. 말 κ·ΈλŒ€λ‘œ ν΄λž˜μŠ€κ°€ 좔상화 λœλ‹€λŠ” λŠλ‚Œμ΄λ‹€. λ˜ν•œ abstractλŠ” 클래슀 λ‚΄λΆ€μ—μ„œ μ •μ˜λœ λ©”μ„œλ“œ μ•žμ—λ„ 뢙을 수 μžˆλ‹€. κ·Έ 클래슀λ₯Ό 상속 λ°›λŠ” μžμ‹ ν΄λž˜μŠ€μ—μ„œλŠ” abstractκ°€ 뢙은 λ©”μ„œλ“œλ₯Ό λ°˜λ“œμ‹œ μ •μ˜ν•΄μ£Όμ–΄μ•Ό ν•œλ‹€.

abstract class Aligator { ... } const aligator = new Aligator // Error: cannot create an instance of abstract class class Shark { ... abstract eatHuman() {}; } class BabyShark extends Shark { ... eatHuman() {...} }



νƒ€μž…μŠ€ν¬λ¦½νŠΈ νƒ€μž… ν˜Έν™˜μ„±

ν• λ‹Ήν•  수 μžˆλŠ” νƒ€μž…/κ°’μ˜ λ²”μœ„λ‘œ 따지면 νŽΈν•˜λ‹€.

νƒ€μž… ν˜Έν™˜μ„±μ€ 정적 νƒ€μž… μ–Έμ–΄κ°€ κ°€μ§€λŠ” νŠΉμ„±μ΄λ‹€. μ–΄λ–€ νƒ€μž…μ„ λ‹€λ₯Έ νƒ€μž…μœΌλ‘œ μ·¨κΈ‰ν•  수 μžˆμ„μ§€? ν˜Έν™˜ν•΄μ„œ μ‚¬μš©ν•  수 μžˆμ„μ§€λ₯Ό νŒλ‹¨ν•΄μ£ΌλŠ” νŠΉμ„±μ΄λΌκ³  μƒκ°ν•˜λ©΄ λœλ‹€. νƒ€μž…μ— ν˜Έν™˜μ„±μ„ λ”°μ§€λŠ” μ΄μœ λŠ” 컴파일 λ‹¨κ³„μ—μ„œ ν˜Έν™˜λ˜μ§€ μ•ŠλŠ” 것을 μ°ΎκΈ° μœ„ν•¨μ΄λ‹€.

νŠΉμ • λ³€μˆ˜λ₯Ό λ‹€λ₯Έ λ³€μˆ˜μ— ν• λ‹Ήν•˜κΈ° μœ„ν•΄μ„œλŠ” κ·Έ νƒ€μž…μ— 할당이 κ°€λŠ₯ν•΄μ•Ό ν•œλ‹€. 즉, ν• λ‹Ήν•˜λ €λŠ” λŒ€μƒμ˜ νƒ€μž…μ— ν˜Έν™˜λ˜μ–΄μ•Ό ν•œλ‹€λŠ” λœ»μ΄λ‹€. ν˜Έν™˜ μ—¬λΆ€λŠ” νƒ€μž…μ˜ λ²”μœ„κ°€ 큰 것에 μž‘μ€ 것이 ν˜Έν™˜ λœλ‹€κ³  μƒκ°ν•˜λ©΄ 쉽닀.

function boundary(a: number, b: number | string): void { const v1: number | string = a; const v2: number = b; // Error }

μœ„μ˜ μ½”λ“œμ—μ„œ v2의 κ²½μš°μ—λŠ” number νƒ€μž…λ§Œ ν• λ‹Ή κ°€λŠ₯ν•œλ°, number | string의 값이 될 수 μžˆλŠ” bλ₯Ό ν• λ‹Ήν•˜λ €κ³  ν–ˆκΈ° λ•Œλ¬Έμ—, κ·Έ ν• λ‹Ήμ˜ λ²”μœ„ 크기 λΉ„κ΅μ—μ„œ ν˜Έν™˜μ΄ 이루어 질 수 μ—†μ–΄ μ—λŸ¬κ°€ 났닀. string | number > number


Structure Typing

νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” κ°’ 자체둜 νƒ€μž… ν˜Έν™˜μ„±μ„ λΉ„κ΅ν•˜μ§€ μ•ŠλŠ”λ‹€. 값을 가지고 μžˆλŠ” νƒ€μž…μ˜ λ‚΄λΆ€ ꡬ쑰에 κΈ°λ°˜ν•œλ‹€. κ·Έλž˜μ„œ μ„œλ‘œ λ‹€λ₯Έ μ΄λ¦„μœΌλ‘œ μ •μ˜λœ νƒ€μž…λ“€μ˜ λ‚΄λΆ€ ꡬ쑰 즉, μ†μ„±μ˜ 이름과 κ·Έ μ†μ„±μ˜ νƒ€μž…μ΄ κ°™λ‹€λ©΄ νƒ€μž… ν˜Έν™˜μ΄ κ°€λŠ₯ν•˜λ‹€κ³  νŒλ‹¨ν•˜λŠ” 것이닀.

interface Human { name: string; age: number; } interface Unicorn { name: string; age: number; } const woman: Human = { name: '', age: 20 }; const wnicorn: Unicorn = woman; // νƒ€μž…μ΄ ν˜Έν™˜λœλ‹€!

Interface νƒ€μž…μ˜ ν˜Έν™˜μ„±

νŠΉμ • μΈν„°νŽ˜μ΄μŠ€(A)κ°€ λ‹€λ₯Έ μΈν„°νŽ˜μ΄μŠ€(B)둜 ν• λ‹Ήλ˜κΈ° μœ„ν•œ 쑰건은 λ‹€μŒκ³Ό κ°™λ‹€. μ‰½κ²Œ μ΄ν•΄ν•˜κΈ° μœ„ν•΄μ„œ λ“±ν˜Έλ‘œ 크기 비ꡐ λŠλ‚Œμ„ κ°€μ Έκ°€κ² λ‹€.

  • A에 μ •μ˜λœ μ†μ„±μ˜ 이름은 λͺ¨λ‘ B에도 λ™μΌν•˜κ²Œ μžˆμ–΄μ•Ό ν•œλ‹€. A속성이름 <= B속성이름
  • 이름이 같은 속성에 λŒ€ν•΄μ„œ, A의 속성이 B의 속성에 ν• λ‹Ή κ°€λŠ₯ν•΄μ•Ό ν•œλ‹€. A κ°œλ³„ 속성 νƒ€μž… <= B κ°œλ³„ 속성 νƒ€μž…
  • Aκ°€ 할당될 수 μžˆλŠ” κ°’μ˜ λ²”μœ„κ°€ B보닀 λ„“λ‹€. (이 뢀뢄을 잘 이해해야 ν•œλ‹€.)
interface Human { name: string; } interface Shark { name: string; tooth: number; } const baby = { name: 'baby', tooth: '28', poop: true }; const babyHuman: Human = baby; // ok const babyShark: Shark = baby; // Error νƒ€μž… ν˜Έν™˜μ΄ μ•ˆλœλ‹€. babyHuman = babyShark; // 문제 μ—†λ‹€. name이 λ™μΌν•˜κΈ° λ•Œλ¬Έμ΄λ‹€. (κ°’μ˜ λ²”μœ„!)

κ·Έλž˜μ„œ μΈν„°νŽ˜μ΄μŠ€ νƒ€μž…μ˜ ν˜Έν™˜μ„ λ§žμΆœλ•ŒλŠ” μ˜΅μ…”λ„ 속성(?둜 μ •μ˜)에 μ£Όμ˜ν•΄μ•Ό ν•œλ‹€. μ˜΅μ…”λ„ν•œ 속성은 μžˆμ„ μˆ˜λ„ 있고, 없을 μˆ˜λ„ μžˆλŠ” μ†μ„±μ΄λΌμ„œ κ°’μ˜ λ²”μœ„λ₯Ό λ„“μ—¬μ£ΌλŠ” 역할을 ν•˜κ²Œλœλ‹€.


ν•¨μˆ˜μ˜ νƒ€μž… ν˜Έν™˜μ„±

νŠΉμ •ν•œ ν•¨μˆ˜(A)에 λ‹€λ₯Έ ν•¨μˆ˜(B)λ₯Ό ν• λ‹Ήν•˜κΈ° μœ„ν•΄μ„œλŠ” λ‹€μŒμ˜ 쑰건을 λ§Œμ‘±ν•΄μ•Ό ν•œλ‹€. 쑰건을 λ‘˜μ§ΈμΉ˜κ³  κ°€μž₯ μ€‘μš”ν•œ 것은 ν•¨μˆ˜μ˜ μ‹€ν–‰μ‹œμ μ— κ·Έ ν•¨μˆ˜κ°€ μ–΄λ–€ νƒ€μž…μ„ 띄고 μžˆλŠ”μ§€, 그리고 νƒ€μž…μ˜ λ²”μœ„κ°€ 어떀지가 μ€‘μš”ν•˜λ‹€.

  • A의 λ§€κ°œλ³€μˆ˜ κ°œμˆ˜κ°€ B의 κ°œμˆ˜λ³΄λ‹€ λ§Žμ•„μ•Ό ν•œλ‹€. μ‰½κ²Œ μƒκ°ν•΄μ„œ ν•¨μˆ˜λ₯Ό λ™μž‘ν•˜κΈ° μœ„ν•΄ ν•„μš”ν•œ λ§€κ°œλ³€μˆ˜κ°€ λ§Žμ€ 것을 적은 것에 ν• λ‹Ή ν•  수 μ—†λ‹€λŠ” 말이닀.
  • 같은 μœ„μΉ˜μ˜ λ§€κ°œλ³€μˆ˜λŠ” νƒ€μž… ν˜Έν™˜μ„±μ΄ λ§žμ•„μ•Ό ν•œλ‹€.
  • B의 리턴값에 λŒ€ν•œ νƒ€μž…μ΄ A의 리턴값 νƒ€μž…λ³΄λ‹€ κ·Έ λ²”μœ„κ°€ μž‘μ•„μ•Ό ν•œλ‹€.
// 각 ν•¨μˆ˜ νƒ€μž… μ •μ˜ type F1 = (a: number, b: string) => string; type F2 = (a: number, b: string | number) => string; type F3 = (a: number) => string; type F4 = (a: number) => string | number; // ν•¨μˆ˜ let f1: F1 = (a, b) => `${a}, ${b.length}`; let f2: F2 = (a, b) => `${a}, ${b}`; let f3: F3 = (a) => `${a}`; let f4: F4 = (a) => (a < 10 ? a : 'not a'); // ν• λ‹Ή 검사 f1 = f3; // ok -> f1의 λ§€κ°œλ³€μˆ˜κ°€ 더 λ§Žλ‹€. (감당해야 ν•  κ°’μ˜ λ²”μœ„κ°€ μž‘λ‹€.) f3 = f1; // Error -> λ§€κ°œλ³€μˆ˜ 차이가 λ‚œλ‹€. f1 = f2; // ok -> bλΌλŠ” λ§€κ°œλ³€μˆ˜κ°€ f2의 b에 ν˜Έν™˜λœλ‹€. f2 = f1; // Error -> f2의 b λ§€κ°œλ³€μˆ˜μ— λ²”μœ„κ°€ 더 λ„“μ–΄μ„œ ν˜Έν™˜μ΄ λ˜μ§€ μ•ŠλŠ”λ‹€. f4 = f3; // ok f3 = f4; // Error -> f4둜 ν˜ΈμΆœν•  λ•Œ λ°˜ν™˜λ  수 μžˆλŠ” κ°’μ˜ νƒ€μž…μ΄ 더 λ„“λ‹€.
to be continue ..

λͺ©μ°¨

μ΄μ–΄μ§€λŠ” κΈ€,