๐ Today I Learned 11ํ์ฐจ - Dart with ํค์๋ ๐ก
๐ Dart์ with ํค์๋
๐ฏ ํ์ต ๋ชฉํ
extends
(์์)์with
(๋ฏน์ค์ธ)์ ์ฐจ์ด์ ์ดํดํ๊ธฐ- Mixin์ ์ ์์ ์ฌ์ฉ๋ฒ ์ตํ๊ธฐ
- ์บ์คํ ๊ณผ ํ์ ๊ฒ์ฌ ์๋ฆฌ ํ์ ํ๊ธฐ
- ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๋ ๋ฏน์ค์ธ์ ํ์ฉ๋ฒ ํ์ตํ๊ธฐ
๐ ์ฃผ์ ๋ด์ฉ
โญ extends
(์์) vs with
(๋ฏน์ค์ธ)
with
๋ฅผ ์ดํดํ๋ ค๋ฉด ๋จผ์ extends
(์์)์์ ์ฐจ์ด์ ์ ์๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
1. extends
(์์) ๐งฌ
extends
๋ โ~์ด๋คโ (is a) ๊ด๊ณ๋ฅผ ๋ํ๋
๋๋ค. ๋ถ๋ชจ์ ์์ ๊ด๊ณ์ฒ๋ผ, ์์ ํด๋์ค๋ ๋ถ๋ชจ ํด๋์ค์ ๋ชจ๋ ๊ฒ์ ๋ฌผ๋ ค๋ฐ์ต๋๋ค. ์ด๋ ํด๋์ค์ ๊ทผ๋ณธ์ ์ธ ์ ์ฒด์ฑ์ ๊ฒฐ์ ํฉ๋๋ค.
- ์์:
class Dog extends Animal { ... }
- โ๊ฐ๋ ๋๋ฌผ์ด๋ค.โ (Dog is an Animal.)
- ํน์ง: Dart์์๋ ๋จ ํ๋์ ํด๋์ค๋ง
extends
ํ ์ ์์ต๋๋ค. (๋ถ๋ชจ๋ ํ๋)
2. with
(๋ฏน์ค์ธ) ๐
with
๋ โ~๋ฅผ ํ ์ ์๋คโ (can do) ๊ด๊ณ๋ฅผ ๋ํ๋
๋๋ค. ์์์ฒ๋ผ ์ ์ฒด์ฑ์ ๋ฌผ๋ ค๋ฐ๋ ๊ฒ์ด ์๋๋ผ, ํน์ ๊ธฐ๋ฅ(๋ฅ๋ ฅ)๋ง ์ ๊ฐ์ ธ์์ ์ฅ์ฐฉํ๋ ๊ฐ๋
์
๋๋ค.
- ๋น์ : ์๋์ฐจ์ โํฐ๋ณด ์์งโ์ด๋ โ๋ค๋น๊ฒ์ด์
โ ๊ฐ์ ๋ถํ์ ์ถ๊ฐ๋ก ์ฅ์ฐฉํ๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค. ์๋์ฐจ์ ๋ณธ์ง(
extends Vehicle
)์ ๋ณํ์ง ์์ง๋ง, ์๋ก์ด ๋ฅ๋ ฅ(with Turbo, with Navigation
)์ด ์๊ธฐ๋ ๊ฒ์ด์ฃ . - ํน์ง: ์ฌ๋ฌ ๊ฐ์ ๊ธฐ๋ฅ์
with
ํค์๋ ๋ค์ ์ผํ(,)๋ก ๊ตฌ๋ถํ์ฌ ์ฅ์ฐฉํ ์ ์์ต๋๋ค.
โก with
ํค์๋ ์ฌ์ฉ๋ฒ๊ณผ ์์
with
๋ ์ด๋ ๊ฒ โ๊ธฐ๋ฅ ๋ฉ์ด๋ฆฌโ์ธ Mixin์ ํด๋์ค์ ์ ์ฉํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
๊ฐ๋จํ ์์๋ฅผ ๋ค์ด๋ณด๊ฒ ์ต๋๋ค. โ๋ ์ ์๋โ ๋ฅ๋ ฅ๊ณผ โํค์์น ์ ์๋โ ๋ฅ๋ ฅ์ Mixin์ผ๋ก ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
1. ๋ฅ๋ ฅ(Mixin) ์ ์ํ๊ธฐ
mixin
ํค์๋๋ฅผ ์ฌ์ฉํด ์ฌ์ฌ์ฉํ ๊ธฐ๋ฅ๋ค์ ์ ์ํฉ๋๋ค.
// ๋๋ ๋ฅ๋ ฅ์ ์ ์
mixin CanFly {
void fly() {
print("ํ๋์ ๋ฉ๋๋ค. ํจํจ~");
}
}
// ํค์์น๋ ๋ฅ๋ ฅ์ ์ ์
mixin CanSwim {
void swim() {
print("๋ฌผ์์ ํค์์นฉ๋๋ค. ์ฒจ๋ฒ์ฒจ๋ฒ!");
}
}
2. ํด๋์ค์ ๋ฅ๋ ฅ(with
) ์ฅ์ฐฉํ๊ธฐ
์ด์ ์ด ๋ฅ๋ ฅ๋ค์ ์ฌ๋ฌ ํด๋์ค์ with
ํค์๋๋ก ์ฅ์ฐฉํด ๋ณด๊ฒ ์ต๋๋ค.
// '์'๋ ๊ธฐ๋ณธ์ ์ผ๋ก '๋๋ฌผ'์ด๋ฉฐ, '๋๋ ๋ฅ๋ ฅ'์ ๊ฐ์ง๋๋ค.
class Bird extends Animal with CanFly {
// Bird ํด๋์ค๋ ์ด์ fly() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
}
// '์ค๋ฆฌ'๋ '๋๋ฌผ'์ด๋ฉฐ, '๋๋ ๋ฅ๋ ฅ'๊ณผ 'ํค์์น๋ ๋ฅ๋ ฅ'์ ๋ชจ๋ ๊ฐ์ง๋๋ค.
class Duck extends Animal with CanFly, CanSwim {
// Duck ํด๋์ค๋ ์ด์ fly()์ swim() ๋ฉ์๋๋ฅผ ๋ชจ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
}
// '๋ฌผ๊ณ ๊ธฐ'๋ '๋๋ฌผ'์ด๋ฉฐ, 'ํค์์น๋ ๋ฅ๋ ฅ'๋ง ๊ฐ์ง๋๋ค.
class Fish extends Animal with CanSwim {
// Fish ํด๋์ค๋ ์ด์ swim() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
}
void main() {
var duck = Duck();
duck.fly(); // ์ถ๋ ฅ: ํ๋์ ๋ฉ๋๋ค. ํจํจ~
duck.swim(); // ์ถ๋ ฅ: ๋ฌผ์์ ํค์์นฉ๋๋ค. ์ฒจ๋ฒ์ฒจ๋ฒ!
var fish = Fish();
fish.swim(); // ์ถ๋ ฅ: ๋ฌผ์์ ํค์์นฉ๋๋ค. ์ฒจ๋ฒ์ฒจ๋ฒ!
// fish.fly(); // ์๋ฌ! Fish๋ CanFly ๋ฅ๋ ฅ์ด ์์ต๋๋ค.
}
์ด์ฒ๋ผ with
๋ฅผ ์ฌ์ฉํ๋ฉด ์์ ๊ด๊ณ์ ์ฝํ์ง ์๊ณ , ์ํ๋ ํด๋์ค์ ํ์ํ ๊ธฐ๋ฅ๋ง ์์ ๋กญ๊ฒ ์ถ๊ฐํ์ฌ ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ์ ๊ทน๋ํํ ์ ์์ต๋๋ค.
๐ ์ด์ ์ค๋ช ์ ๋ค์ ์ ์ฉํด๋ณด๊ธฐ
์ด์ TickerProviderStateMixin
์ค๋ช
์ ๋์๋ ์ฝ๋๋ฅผ ๋ค์ ๋ณด๋ฉด ์๋ฒฝํ๊ฒ ์ดํดํ ์ ์์ต๋๋ค.
class _MyAnimationState extends State<MyAnimation> with TickerProviderStateMixin { ... }
extends State<MyAnimation>
- ์ด ํด๋์ค์ ์ ์ฒด์ฑ์
State
์ด๋ค. (โ๋๋MyAnimation
์ ์ํ ๊ฐ์ฒด์ด๋ค.โ)
- ์ด ํด๋์ค์ ์ ์ฒด์ฑ์
with TickerProviderStateMixin
- ๊ทธ๋ฆฌ๊ณ ๋๋
TickerProviderStateMixin
์ด ์ ๊ณตํ๋ ๋ฅ๋ ฅ์ ์ถ๊ฐ๋ก ์ฅ์ฐฉํ๋ค. (โ๋๋ Ticker๋ฅผ ์ ๊ณตํ ์ ์๋ค.โ)
- ๊ทธ๋ฆฌ๊ณ ๋๋
๐ ํต์ฌ ๊ฐ๋ ์ ๋ฆฌ
๊ตฌ๋ถ | extends (์์) |
with (๋ฏน์ค์ธ) |
---|---|---|
๊ด๊ณ | is a (A๋ B์ด๋ค) | can do (A๋ B๋ฅผ ํ ์ ์๋ค) |
๊ฐ์ | ๋จ ํ๋๋ง ๊ฐ๋ฅ | ์ฌ๋ฌ ๊ฐ ๊ฐ๋ฅ |
๋ชฉ์ | ๋ถ๋ชจ-์์ ๊ด๊ณ์ ํต์ฌ ์ ์ฒด์ฑ ์ ์ | ์ฌ๋ฌ ํด๋์ค์ ๊ฑธ์ณ ์ฝ๋(๊ธฐ๋ฅ)๋ฅผ ์ฌ์ฌ์ฉ |
๋น์ | ํ์ฐ, ๊ฐ๋ฌธ ๐งฌ | ์คํฌ ์ต๋, ์ฅ๋น ์ฅ์ฐฉ ๐ |
๐ป ์ค์ต ๋ฐ ์์
๐ค ์ง๋ฌธ: with์ผ๋ก ์์๋ฐ์ ํด๋์ค๋ก casting์ ์๋๋ ๊ฑธ๊น?
๊ฒฐ๋ก ๋ถํฐ ๋ง์๋๋ฆฌ๋ฉด, ๋ค, ๊ฐ๋ฅํฉ๋๋ค.
with
ํค์๋๋ก ์ถ๊ฐ๋ ๋ฏน์ค์ธ(Mixin)์ ํด๋น ํด๋์ค๊ฐ ๊ทธ ๋ฏน์ค์ธ์ ํ์
์ ๊ตฌํ(implements)ํ๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผ๋ฉ๋๋ค. ๋ฐ๋ผ์ ๊ทธ ๋ฏน์ค์ธ ํ์
์ผ๋ก ์บ์คํ
(ํ๋ณํ)ํ๊ฑฐ๋ ํ์
๊ฒ์ฌ๋ฅผ ํ ์ ์์ต๋๋ค.
๐ก with
์ implements
์ ์จ๊ฒจ์ง ๊ด๊ณ
์ด๊ฒ์ด ๊ฐ๋ฅํ ์ด์ ๋ฅผ ์ดํดํ๋ ค๋ฉด Dart๊ฐ with
๋ฅผ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ๋์ง ์์์ผ ํฉ๋๋ค.
class MyClass with MyMixin { ... }
์ ์ฝ๋๋ ์ฌ์ค์ Dart ๋ด๋ถ์ ์ผ๋ก ์๋์ ๊ฐ์ด ๋์ํฉ๋๋ค.
class MyClass implements MyMixin { ... }
with
๋ implements
(์ธํฐํ์ด์ค ๊ตฌํ)์ ํน๋ณํ ๋ฒ์ ์ด๋ผ๊ณ ์๊ฐํ ์ ์์ต๋๋ค. implements
๋ โ์ด๋ฐ์ด๋ฐ ๊ธฐ๋ฅ๋ค์ ๊ฐ์ง๊ณ ์๋ค๊ณ ์ฝ์ํ ๊ฒโ๋ผ๊ณ ์ ์ธ๋ง ํ๋ ๊ฒ์ด๋ผ ๋ชจ๋ ๋ฉ์๋๋ฅผ ์ง์ ๊ตฌํํด์ผ ํ์ง๋ง, with
๋ ์ ์ธ๊ณผ ๋์์ ๋ฏน์ค์ธ์ ์ด๋ฏธ ์์ฑ๋ ๊ธฐ๋ฅ๋ค์ ๊ทธ๋๋ก ๊ฐ์ ธ์์ ์๋์ผ๋ก ๊ตฌํํด์ค๋๋ค.
๊ฒฐ๊ตญ, with MyMixin
์ ์ฌ์ฉํ ํด๋์ค๋ MyMixin
์ **ํ์ ํ์
(subtype)**์ด ๋๋ฏ๋ก, ํ์
๊ฒ์ฌ(is
)์ ์บ์คํ
(as
)์ด ๋ชจ๋ ๊ฐ๋ฅํด์ง๋ ๊ฒ์
๋๋ค.
๐ป ํ์ ์บ์คํ ์ค์ต
์ด์ ๋ต๋ณ์์ ์ฌ์ฉํ๋ CanFly
, CanSwim
์์ ๋ก ์ง์ ํ์ธํด ๋ณด๊ฒ ์ต๋๋ค.
// ๋ฅ๋ ฅ(Mixin) ์ ์
mixin CanFly {
void fly() => print("ํ๋์ ๋ฉ๋๋ค. ํจํจ~");
}
mixin CanSwim {
void swim() => print("๋ฌผ์์ ํค์์นฉ๋๋ค. ์ฒจ๋ฒ์ฒจ๋ฒ!");
}
// '์ค๋ฆฌ'๋ ๋๋ ๋ฅ๋ ฅ๊ณผ ํค์์น๋ ๋ฅ๋ ฅ์ ๋ชจ๋ ๊ฐ์ง
class Duck with CanFly, CanSwim {}
// ๋นํ์ ์ํค๋ ํจ์ (CanFly ํ์
์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์)
void makeItFly(CanFly flyer) {
print("${flyer.runtimeType} ๊ฐ์ฒด๊ฐ ๋ ์๊ฐ๋๋ค.");
flyer.fly();
}
void main() {
var duck = Duck();
// 1. ํ์
๊ฒ์ฌ (is ํค์๋)
// duck์ CanFly ํ์
์ธ๊ฐ? -> true
print('duck is CanFly: ${duck is CanFly}');
// duck์ CanSwim ํ์
์ธ๊ฐ? -> true
print('duck is CanSwim: ${duck is CanSwim}');
// duck์ String ํ์
์ธ๊ฐ? -> false
print('duck is String: ${duck is String}');
print('---');
// 2. ๋ช
์์ ์บ์คํ
(as ํค์๋)
// duck ๊ฐ์ฒด๋ฅผ CanFly ํ์
์ผ๋ก ๊ฐ์ฃผํ์ฌ flyer ๋ณ์์ ํ ๋น
CanFly flyer = duck as CanFly;
flyer.fly();
print('---');
// 3. ์ค์ฉ์ ์ธ ์์: ํจ์์ ์ ๋ฌํ๊ธฐ
// makeItFly ํจ์๋ CanFly ํ์
์ ์๊ตฌํ๋๋ฐ, duck์ CanFly์ ํ์ ํ์
์ด๋ฏ๋ก ์ ๋ฌ ๊ฐ๋ฅ
makeItFly(duck);
}
์คํ ๊ฒฐ๊ณผ:
duck is CanFly: true
duck is CanSwim: true
duck is String: false
---
ํ๋์ ๋ฉ๋๋ค. ํจํจ~
---
Duck ๊ฐ์ฒด๊ฐ ๋ ์๊ฐ๋๋ค.
ํ๋์ ๋ฉ๋๋ค. ํจํจ~
๐ฏ ํ์ ์บ์คํ ํต์ฌ ์ ๋ฆฌ
- ์บ์คํ
๊ฐ๋ฅํ๋ค:
with
๋ก ์ถ๊ฐํ ๋ฏน์ค์ธ์ ํด๋น ํด๋์ค์ ํ์ ์ค ํ๋๋ก ์ธ์ ๋ฉ๋๋ค. - ์ด์ :
with
๋ ๋ฏน์ค์ธ์ **๊ตฌํ(implements)**ํ๋ ๊ฒ๊ณผ ๊ฐ์์, ํด๋์ค๋ ๋ฏน์ค์ธ์ ํ์ ํ์ ์ด ๋๊ธฐ ๋๋ฌธ์ ๋๋ค. - ํ์ฉ: ์ด ํน์ง ๋๋ถ์ ํน์ ๊ธฐ๋ฅ(๋ฏน์ค์ธ)์ ๊ฐ์ง ๊ฐ์ฒด๋ค๋ง ์ธ์๋ก ๋ฐ๋ ์ ์ฐํ ํจ์๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
makeItFly(CanFly flyer)
ํจ์๊ฐDuck
๋ฟ๋ง ์๋๋ผwith CanFly
๋ฅผ ์ฌ์ฉํ ์ด๋ค ๊ฐ์ฒด(Bird
,Airplane
๋ฑ)๋ผ๋ ๋ฐ์ ์ ์๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ .
Q) ๊ธฐ์กด์ c#์ ์จ์๋ ์ ์ฅ์์ ์๊ฐ์ ํด๋ณด๋ฉด, interface์ ๊ฐ์ด ์์ ํ ๊ตฌํ(implenment)์ ์๋ ๊ฒ ๊ฐ๊ณ , abstract์ ๋น์ทํ ๋๋์ธ๋ฐ, ๊ทธ๋ฌ๋ฉด abstract์์ virtual๋ก ์์ ๋ฐ์ ๋ฉ์๋๋ฅผ override ํ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ ์ ํ ์ฌ์ฉ์ด ๊ฐ๋ฅํ ๊ฑธ๊น? ๊ทธ๋ฆฌ๊ณ mixin ์ ๋ฉ์๋๋ง ๊ธฐ๋ฅ์ผ๋ก ์ฅ์ฐฉํ ์ ์๋ ๊ฑธ๊น?
C# ๊ฐ๋ฐ์ ์
์ฅ์์ ์ ๋ง ์ข์ ์ง๋ฌธ์
๋๋ค. C#์ interface
, abstract class
, virtual
/override
๊ฐ๋
๊ณผ Dart์ mixin
์ ๋น๊ตํ๋ฉด ๊ทธ ์ฐจ์ด์ ์ ๋ช
ํํ ์ดํดํ ์ ์์ต๋๋ค.
๋ ๊ฐ์ง ์ง๋ฌธ์ ๋ํด ๋๋ ์ ๋ต๋ณํด ๋๋ฆด๊ฒ์.
โก 1. Mixin ๋ฉ์๋ ์ฌ์ ์(Override)์ ๋์ ๋ฐฉ์
๊ฒฐ๋ก ๋ถํฐ ๋ง์๋๋ฆฌ๋ฉด, ๋ค, ๋ฏน์ค์ธ์ ๋ฉ์๋๋ฅผ ์ฌ์ ์(override)ํ ์ ์์ต๋๋ค. ํ์ง๋ง C#์ abstract class
์ virtual
/override
๋์ ๋ฐฉ์๊ณผ๋ ๊ทผ๋ณธ์ ์ธ ์ฐจ์ด๊ฐ ์์ต๋๋ค.
C#์ ๊ฐ๋ ๊ณผ ๋น๊ตํ์ฌ ๋ฏน์ค์ธ์ ์ดํดํ๋ ๊ฐ์ฅ ์ข์ ๋น์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
interface
(C#): **โ์ค๊ณ๋โ**์ ๊ฐ๊น์ต๋๋ค. ์ด๋ค ๊ธฐ๋ฅ๋ค์ด ์์ด์ผ ํ๋์ง โ์ฝ์โ๋ง ํ๊ณ , ์ค์ ๊ตฌํ์ ํด๋์ค์์ ๋ชจ๋ ํด์ผ ํฉ๋๋ค.abstract class
(C#): **โ๋ฐ์ฏค ์ง์ด์ง ์งโ**๊ณผ ๊ฐ์ต๋๋ค. ์ผ๋ถ ๊ธฐ๋ฅ(virtual
๋๋ ์ผ๋ฐ ๋ฉ์๋)์ ์ด๋ฏธ ๊ตฌํ๋์ด ์๊ณ , ์ผ๋ถ(abstract
๋ฉ์๋)๋ ๋น์ด ์์ด์ ์์๋ฐ๋ ํด๋์ค๊ฐ ๋ฐ๋์ ์์ฑํด์ผ ํฉ๋๋ค.mixin
(Dart): **โ์กฐ๋ฆฝ์ ๋ถํโ ๋๋ โํ๋ฌ๊ทธ์ธโ**์ ๊ฐ๊น์ต๋๋ค. ์ด๋ฏธ ์์ฑ๋ ๊ธฐ๋ฅ ๋ฉ์ด๋ฆฌ๋ฅผ ๊ฐ์ ธ์ ๋ด ํด๋์ค์ ๊ทธ๋๋ก โ์ฅ์ฐฉโํ๋ ๊ฐ๋ ์ ๋๋ค.
๋์ ๋ฐฉ์์ ์ฐจ์ด: ์์ ์ฒด์ธ vs ์ฐ์ ์์
C#์ override
๋ ๋ถ๋ชจ ํด๋์ค(base
)์ virtual
๋ฉ์๋๋ฅผ ์์ ํด๋์ค์์ ์ฌ์ ์ํ๋, ๋ช
ํํ ์์ ๊ณ์ธต ๊ตฌ์กฐ ์์์ ๋์ํฉ๋๋ค.
๋ฐ๋ฉด, ๋ฏน์ค์ธ์ **โ์ฐ์ ์์โ**์ ๋ฐ๋ผ ์ ์ฉ๋ฉ๋๋ค. ์ฌ๋ฌ ๋ฏน์ค์ธ์ ์ฌ์ฉํ๊ฑฐ๋ ํด๋์ค ์์ฒด์ ๊ฐ์ ์ด๋ฆ์ ๋ฉ์๋๊ฐ ์๋ค๋ฉด, ์ ํด์ง ๊ท์น์ ๋ฐ๋ผ ์ด๋ค ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ง ๊ฒฐ์ ํฉ๋๋ค.
๊ท์น: class
์ ์ธ๋ถ์ ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ ์์๋ก ์ ์ฉ๋๋ค.
class MyRobot extends Machine with Walker, Runner { ... }
๋ง์ฝ Walker
์ Runner
๋ฏน์ค์ธ ๋ชจ๋์ move()
๋ผ๋ ๋ฉ์๋๊ฐ ์๋ค๋ฉด, MyRobot
์ธ์คํด์ค์์ move()
๋ฅผ ํธ์ถํ๋ฉด ๊ฐ์ฅ ๋ง์ง๋ง์ with
๋ก ์ถ๊ฐ๋ Runner
์ move()
๊ฐ ์คํ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ง์ฝ MyRobot
ํด๋์ค ์์ฒด์์ move()
๋ฉ์๋๋ฅผ override
ํ๋ฉด, MyRobot
์ move()
๊ฐ ์ต์ฐ์ ์์๋ฅผ ๊ฐ๊ฒ ๋ฉ๋๋ค.
์ฝ๋ ์์
mixin Walker {
void move() {
print("๋ ๋ฐ๋ก ๊ฑท์ต๋๋ค.");
}
}
mixin Runner {
void move() {
print("๋น ๋ฅด๊ฒ ๋ฌ๋ฆฝ๋๋ค!"); // Walker์ move()์ ์ด๋ฆ์ด ๊ฐ์
}
}
// 1. Runner์ move()๊ฐ ์ฐ์ ์์๋ฅผ ๊ฐ์ง
class Robot with Walker, Runner {}
// 2. ํด๋์ค ์์ฒด์ move()๊ฐ ์ต์ฐ์ ์์๋ฅผ ๊ฐ์ง
class AdvancedRobot with Walker, Runner {
@override
void move() {
print("๋ถ์คํฐ๋ฅผ ์ผ๊ณ ๋ ์๊ฐ๋๋ค!");
// super.move(); // ํธ์ถ ์ ๋ฐ๋ก ์ ์ฐ์ ์์์ธ Runner์ move()๊ฐ ์คํ๋จ
}
}
void main() {
var robot = Robot();
robot.move(); // ์ถ๋ ฅ: ๋น ๋ฅด๊ฒ ๋ฌ๋ฆฝ๋๋ค!
var advancedRobot = AdvancedRobot();
advancedRobot.move(); // ์ถ๋ ฅ: ๋ถ์คํฐ๋ฅผ ์ผ๊ณ ๋ ์๊ฐ๋๋ค!
}
์ ๋ฆฌ: C#์
override
๊ฐ ๋ถ๋ชจ-์์ ๊ฐ์ ์์ง์ ์ฌ์ ์๋ผ๋ฉด, Dart ๋ฏน์ค์ธ์ ์ฌ์ ์๋ ํด๋์ค ์์ฒด์ ๊ตฌํ์ด ๋ฏน์ค์ธ์ ๊ตฌํ์ ๋ฎ์ด์ฐ๋(์ฐ์ ํ๋) ๋ฐฉ์์ ๋ ๊ฐ๊น์ต๋๋ค.super
ํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐ๋ก ๋ค์ ์ฐ์ ์์์ ๋ฏน์ค์ธ ๋ฉ์๋๋ฅผ ํธ์ถํ ์๋ ์์ต๋๋ค.
โก 2. Mixin์ด ๊ฐ์ง ์ ์๋ ๋ฉค๋ฒ
์๋์, ๋ฏน์ค์ธ์ ๋ฉ์๋๋ฟ๋ง ์๋๋ผ ๋ณ์(ํ๋กํผํฐ), Getter/Setter ๋ฑ๋ ํฌํจํ ์ ์์ต๋๋ค.
๋ฏน์ค์ธ์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ **โ์ฝ๋ ๋ฉ์ด๋ฆฌโ**์ด๋ฏ๋ก, ์ํ(state)๋ฅผ ์ ์ฅํ๋ ๋ณ์์ ๊ทธ ์ํ๋ฅผ ์กฐ์ํ๋ ํ์(method)๋ฅผ ๋ชจ๋ ๊ฐ์ง ์ ์์ต๋๋ค.
์ฝ๋ ์์
mixin BatteryManager {
// 1. ๋ณ์ (ํ๋กํผํฐ)
double _batteryLevel = 100.0;
// 2. Getter
double get batteryStatus => _batteryLevel;
// 3. ๋ฉ์๋
void usePower(double amount) {
_batteryLevel -= amount;
if (_batteryLevel < 0) {
_batteryLevel = 0;
}
print("์ ๋ ฅ ์ฌ์ฉ! ํ์ฌ ๋ฐฐํฐ๋ฆฌ: ${_batteryLevel.toStringAsFixed(1)}%");
}
void charge() {
_batteryLevel = 100.0;
print("์ถฉ์ ์๋ฃ!");
}
}
class Drone with BatteryManager {
void fly() {
print("๋๋ก ๋นํ ์์...");
usePower(15.5); // ๋ฏน์ค์ธ์ ๋ฉ์๋์ ๋ณ์๋ฅผ ๋ด ๊ฒ์ฒ๋ผ ์ฌ์ฉ
}
}
void main() {
var myDrone = Drone();
myDrone.fly(); // ์ถ๋ ฅ: ๋๋ก ๋นํ ์์... -> ์ ๋ ฅ ์ฌ์ฉ! ํ์ฌ ๋ฐฐํฐ๋ฆฌ: 84.5%
// ๋ฏน์ค์ธ์ Getter์๋ ์ ๊ทผ ๊ฐ๋ฅ
print("๋๋ก ๋ฐฐํฐ๋ฆฌ ์ํ: ${myDrone.batteryStatus}%"); // ์ถ๋ ฅ: ๋๋ก ๋ฐฐํฐ๋ฆฌ ์ํ: 84.5%
}
์ด์ฒ๋ผ BatteryManager
๋ฏน์ค์ธ์ ๋ฐฐํฐ๋ฆฌ ์๋์ด๋ผ๋ ์ํ(_batteryLevel
)์ ๊ด๋ จ ๋์(usePower
, charge
)์ ๋ชจ๋ ํฌํจํ๊ณ ์์ผ๋ฉฐ, Drone
ํด๋์ค๋ ์ด ๊ธฐ๋ฅ๋ค์ ๊ทธ๋๋ก โ์ฅ์ฐฉโํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๐ค ์ง๋ฌธ: ์ Mixin์ด ํ์ํ๊ฐ?
์ง๋ฌธ: ์ ์ด๋ฐ ๊ตฌ์กฐ๊ฐ ํ์ํ ๊ฑธ๊น? ์ด์ฐจํผ ์์์ ๋ฐ์๋ ๋ถ๋ชจ ํด๋์ค์ ์๋ ๊ธฐ๋ฅ๋ค์ ๊ฐ์ง๊ณ ์์ ์ฌ์ฉํ ์ ์๋๋ฐ ๋ง์ด์ง?
์ ๋ง ์ข์ ์ง๋ฌธ์ ๋๋ค. ๊ทธ ์ง๋ฌธ์ด์ผ๋ง๋ก ๋ฏน์ค์ธ(Mixin)์ ์กด์ฌ ์ด์ ๋ฅผ ๊ดํตํ๋ ํต์ฌ์ ๋๋ค.
๊ฒฐ๋ก ๋ถํฐ ๋ง์๋๋ฆฌ๋ฉด, ์์๋ง์ผ๋ก๋ ํด๊ฒฐํ๊ธฐ ์ด๋ ค์ด โ์ฝ๋ ์ค๋ณตโ ๋ฌธ์ ๋ฅผ ๋งค์ฐ ์ ์ฐํ๊ณ ์ฐ์ํ๊ฒ ํด๊ฒฐํ๊ธฐ ์ํด์์ ๋๋ค. ํนํ ์๋ก ๋ค๋ฅธ ์์ ๊ณ์ธต์ ์๋ ํด๋์ค๋ค์ด ๊ณตํต๋ ๊ธฐ๋ฅ์ ๊ฐ์ ธ์ผ ํ ๋ ๋ฏน์ค์ธ์ ์ง์ ํ ๊ฐ์น๊ฐ ๋๋ฌ๋ฉ๋๋ค.
โ ๏ธ ์์๋ง์ผ๋ก๋ ๋ถ์กฑํ ์ด์ : โ๋ค์ด์๋ชฌ๋ ๋ฌธ์ โ
๋๋ถ๋ถ์ ๊ฐ์ฒด ์งํฅ ์ธ์ด(C#, Java, Dart ํฌํจ)๋ ๋จ์ผ ์์๋ง ํ์ฉํฉ๋๋ค. ์ฆ, ํ๋์ ํด๋์ค๋ ๋จ ํ๋์ ๋ถ๋ชจ ํด๋์ค๋ง ๊ฐ์ง ์ ์์ฃ . ์ด ์ ์ฝ ๋๋ฌธ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
๊ฐ๋จํ ๊ฒ์ ์บ๋ฆญํฐ ์์๋ฅผ ๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
Character
๋ผ๋ ์ต์์ ๋ถ๋ชจ ํด๋์ค๊ฐ ์์ต๋๋ค.Knight
์Magician
์Character
๋ฅผ ์์๋ฐ์ต๋๋ค.Paladin
์ด๋ผ๋ ์๋ก์ด ์บ๋ฆญํฐ๋ฅผ ๋ง๋ค๊ณ ์ถ์ต๋๋ค. ํ๋ผ๋์ ๊ธฐ์ฌ์ ๋ฅ๋ ฅ(๊ฒ์ )๊ณผ ๋ง๋ฒ์ฌ์ ๋ฅ๋ ฅ(์น์ ๋ง๋ฒ)์ ๋ชจ๋ ๊ฐ์ง๋๋ค.
์์๋ง ์ฌ์ฉํ๋ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น์?
class Paladin extends Knight { ... }
- ์ด๋ ๊ฒ ํ๋ฉด ๊ธฐ์ฌ์ ๋ฅ๋ ฅ์ ๋ฌผ๋ ค๋ฐ์ง๋ง, ๋ง๋ฒ์ฌ์ ๋ฅ๋ ฅ์ ๋ฐ์ ์ ์์ต๋๋ค. ๊ฒฐ๊ตญ
Magician
ํด๋์ค์ ์๋ ์น์ ๋ง๋ฒ ์ฝ๋๋ฅผPaladin
ํด๋์ค์ ๋ณต์ฌํด์ ๋ถ์ฌ๋ฃ์ด์ผ ํฉ๋๋ค.
- ์ด๋ ๊ฒ ํ๋ฉด ๊ธฐ์ฌ์ ๋ฅ๋ ฅ์ ๋ฌผ๋ ค๋ฐ์ง๋ง, ๋ง๋ฒ์ฌ์ ๋ฅ๋ ฅ์ ๋ฐ์ ์ ์์ต๋๋ค. ๊ฒฐ๊ตญ
class Paladin extends Magician { ... }
- ๋ฐ๋๋ก ํ๋ฉด ๊ฒ์ ์ฝ๋๋ฅผ ๋ณต์ฌํด์ ๋ถ์ฌ๋ฃ์ด์ผ ํฉ๋๋ค.
์ด๋ค ๋ฐฉ๋ฒ์ ์ ํํ๋ ์ฝ๋ ์ค๋ณต์ด ๋ฐ์ํฉ๋๋ค. ๋์ค์ ์น์ ๋ง๋ฒ์ ์ฑ๋ฅ์ ์์ ํ๋ ค๋ฉด Magician
๊ณผ Paladin
๋ ํด๋์ค๋ฅผ ๋ชจ๋ ๊ณ ์ณ์ผ ํ๋ ๋์ฐํ ์ํฉ์ด ์๊ธฐ์ฃ .
์ด์ฒ๋ผ ์ฌ๋ฌ ๋ถ๋ชจ์ ํน์ง์ ๋์์ ๋ฌผ๋ ค๋ฐ๊ณ ์ถ์ ๋ ๋จ์ผ ์์์ ํ๊ณ๋ก ์ธํด ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ **โ๋ค์ด์๋ชฌ๋ ๋ฌธ์ (Diamond Problem)โ**๋ผ๊ณ ๋ถ๋ฆ ๋๋ค.
C#์์๋ ์ด ๋ฌธ์ ๋ฅผ
interface
๋ก ์ผ๋ถ ํด๊ฒฐํฉ๋๋ค.IHasSwordSkills
,IHasHealingMagic
๊ฐ์ ์ธํฐํ์ด์ค๋ฅผ ๋ง๋ค์ดPaladin
์ด ๋ ๋ค ๊ตฌํ(implements)ํ๊ฒ ํ ์ ์์ฃ . ํ์ง๋ง ์ธํฐํ์ด์ค๋ โ๋ฌด์์ ํ ์ ์๋์งโ๋ง ์ ์ํ ๋ฟ, โ์ด๋ป๊ฒ ํ๋์งโ์ ๋ํ ์ค์ ์ฝ๋(๊ตฌํ)๋ฅผ ์ ๊ณตํ์ง ์๊ธฐ ๋๋ฌธ์ ๊ฒฐ๊ตญ ์ฝ๋ ์ค๋ณต ๋ฌธ์ ๋ ์ฌ์ ํ ๋จ์ต๋๋ค.
โ ๋ฏน์ค์ธ์ ํด๊ฒฐ์ฑ : ๊ธฐ๋ฅ์ ์กฐํฉ(Composition)
๋ฏน์ค์ธ์ ์ด ๋ค์ด์๋ชฌ๋ ๋ฌธ์ ๋ฅผ ์๋ฒฝํ๊ฒ ํด๊ฒฐํฉ๋๋ค. ํต์ฌ์ ์ธ ๋ฅ๋ ฅ๋ค์ โ๋ถํโ์ฒ๋ผ ๋ง๋ค์ด๋๊ณ , ํ์ํ ํด๋์ค์ โ์ฅ์ฐฉโ๋ง ํ๋ฉด ๋ฉ๋๋ค.
1. ๋ฅ๋ ฅ(Mixin)์ ์ ์ํฉ๋๋ค.
mixin SwordSkills {
void attackWithSword() => print("๊ฒ์ผ๋ก ๊ณต๊ฒฉ!");
}
mixin HealingMagic {
void heal() => print("์น์ ๋ง๋ฒ ์์ !");
}
2. ํ์ํ ํด๋์ค์ with
๋ก ์ฅ์ฐฉํฉ๋๋ค.
class Character {}
// ๊ธฐ์ฌ๋ ๊ฒ์ ๋ฅ๋ ฅ์ ์ฅ์ฐฉ
class Knight extends Character with SwordSkills {}
// ๋ง๋ฒ์ฌ๋ ์น์ ๋ง๋ฒ ๋ฅ๋ ฅ์ ์ฅ์ฐฉ
class Magician extends Character with HealingMagic {}
// ํ๋ผ๋์ ๊ฒ์ ๊ณผ ์น์ ๋ง๋ฒ ๋ฅ๋ ฅ์ ๋ชจ๋ ์ฅ์ฐฉ
class Paladin extends Character with SwordSkills, HealingMagic {}
์ด์ Paladin
ํด๋์ค๋ ์ฝ๋๋ฅผ ๋จ ํ ์ค๋ ๋ณต์ฌํ์ง ์๊ณ attackWithSword()
์ heal()
๋ฉ์๋๋ฅผ ๋ชจ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ง์ฝ ์น์ ๋ง๋ฒ์ ์ฝ๋๋ฅผ ์์ ํด์ผ ํ๋ค๋ฉด HealingMagic
๋ฏน์ค์ธ๋ง ์์ ํ๋ฉด ๋ฉ๋๋ค. ์ฝ๋ ์ค๋ณต์ด ์ฌ๋ผ์ง๊ณ ์ ์ง๋ณด์๊ฐ ๋งค์ฐ ์ฌ์์ก์ต๋๋ค.
๐ ์์(extends
) vs ๋ฏน์ค์ธ(with
)์ ์ญํ
๊ตฌ๋ถ | extends (์์) |
with (๋ฏน์ค์ธ) |
---|---|---|
๊ด๊ณ | โis aโ (A๋ B์ด๋ค) | โcan doโ (A๋ B๋ฅผ ํ ์ ์๋ค) |
๋ชฉ์ | ํด๋์ค์ ํต์ฌ ์ ์ฒด์ฑ์ ์ ์ (์์ง์ ๊ด๊ณ) | ์ฌ๋ฌ ํด๋์ค์ ๊ฑธ์ณ ๊ณตํต ๊ธฐ๋ฅ์ ์ฌ์ฌ์ฉ (์ํ์ ์ถ๊ฐ) |
์์ | Paladin is a Character . |
Paladin can do SwordSkills and HealingMagic . |
๐ ๋ง๋ฌด๋ฆฌ
โ ์ค๋ ๋ฐฐ์ด ๊ฒ
extends
vswith
: ์์์ โis aโ ๊ด๊ณ, ๋ฏน์ค์ธ์ โcan doโ ๊ด๊ณ- Mixin ์ ์:
mixin
ํค์๋๋ก ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๊ธฐ๋ฅ ๋ฉ์ด๋ฆฌ ์์ฑ - ํ์
์บ์คํ
:
with
๋ก ์ถ๊ฐํ ๋ฏน์ค์ธ์ผ๋ก ํ์ ์บ์คํ ๊ฐ๋ฅ - ๋ฉ์๋ ์ฌ์ ์: ๋ฏน์ค์ธ์ ๋ฉ์๋๋ฅผ ํด๋์ค์์ ์ค๋ฒ๋ผ์ด๋ ๊ฐ๋ฅ
- ๋ค์ํ ๋ฉค๋ฒ: ๋ฏน์ค์ธ์ ๋ฉ์๋๋ฟ๋ง ์๋๋ผ ๋ณ์, getter/setter๋ ํฌํจ ๊ฐ๋ฅ
- ๋ค์ด์๋ชฌ๋ ๋ฌธ์ ํด๊ฒฐ: ๋จ์ผ ์์์ ํ๊ณ๋ฅผ ๋ฏน์ค์ธ์ผ๋ก ๊ทน๋ณต
๐ ๋ค์ ๊ณํ
- Flutter์์ Mixin ํ์ฉ: TickerProviderStateMixin ๋ฑ ์ค์ ์ฌ์ฉ ์ฌ๋ก ํ์ต
- Advanced Mixin Pattern: ๋ณตํฉ ๋ฏน์ค์ธ๊ณผ ์์ ์ฒด์ธ ์กฐํฉ ์ฐ๊ตฌ
- Performance: ๋ฏน์ค์ธ ์ฌ์ฉ ์ ์ฑ๋ฅ ๊ณ ๋ ค์ฌํญ ํ์ต
๐ก ํต์ฌ: ๋ฏน์ค์ธ์ ์์์ ๋์ฒดํ๋ ๊ฒ์ด ์๋๋ผ, ์์์ ์์ง์ ๊ตฌ์กฐ๋ฅผ ๋ณด์ํ๋ ์ํ์ ๊ธฐ๋ฅ ์กฐํฉ์ ๊ฐ๋ฅํ๊ฒ ํ์ฌ ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ๋์ฑ ํ๋ถํ๊ณ ์ ์ฐํ๊ฒ ๋ง๋ค์ด์ฃผ๋ ํต์ฌ ๋๊ตฌ์ ๋๋ค! ๐งฉ
๋๊ธ๋จ๊ธฐ๊ธฐ