πŸ—οΈ

Dart Classes & OOP

5 constructor types, inheritance, interfaces, Mixin, factory pattern

Dart is fully object-oriented where everything is an object. It provides 5 constructor types (basic, named, initializer list, const, factory), with extends for inheritance, implements for interfaces, and with for Mixins. Factory constructors are commonly used for fromJson serialization, singletons, and conditional subclass returns.

1. 클래슀 기본 ꡬ쑰

Dartμ—μ„œ λͺ¨λ“  것은 객체이며, λͺ¨λ“  κ°μ²΄λŠ” 클래슀의 μΈμŠ€ν„΄μŠ€μž…λ‹ˆλ‹€. ν΄λž˜μŠ€λŠ” ν•„λ“œ, μƒμ„±μž, λ©”μ„œλ“œ, getter/setter둜 κ΅¬μ„±λ©λ‹ˆλ‹€.

class Person { String name; int age; Person(this.name, this.age); void introduce() { print('μ•ˆλ…•ν•˜μ„Έμš”, μ €λŠ” $name이고 $ageμ‚΄μž…λ‹ˆλ‹€.'); } bool get isAdult => age >= 18; set setAge(int newAge) { if (newAge >= 0) { age = newAge; } }}

2. Private 멀버 (_ μ–Έλ”μŠ€μ½”μ–΄)

μ–Έλ”μŠ€μ½”μ–΄(_)둜 μ‹œμž‘ν•˜λŠ” λ©€λ²„λŠ” 라이브러리(파일) μˆ˜μ€€ privateμž…λ‹ˆλ‹€. public getter둜 μ•ˆμ „ν•˜κ²Œ λ…ΈμΆœν•©λ‹ˆλ‹€.

class Person { String name; int _age; Person(this.name, this._age); int get age => _age; void _privateMethod() { print('λ‚΄λΆ€μ—μ„œλ§Œ 호좜 κ°€λŠ₯'); } void publicMethod() { _privateMethod(); }}

3. μƒμ„±μž 5μ’…

3-1. κΈ°λ³Έ μƒμ„±μž (shorthand)

this.name으둜 νŒŒλΌλ―Έν„°λ₯Ό μžλ™ ν• λ‹Ή

Person(this.name, this.age);

3-2. 이름 μžˆλŠ” μƒμ„±μž (Named Constructor)

같은 ν΄λž˜μŠ€μ— μ—¬λŸ¬ μƒμ„±μžλ₯Ό λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€.

Person.guest() { name = 'μ†λ‹˜'; age = 0; } Person.child(this.name) { age = 10; } Person.adult(this.name) { age = 18; } // μ‚¬μš©: Person.guest(), Person.child('아이'), Person.adult('성인')

3-3. μ΄ˆκΈ°ν™” 리슀트 (Initializer List)

μƒμ„±μž λ³Έλ¬Έ μ‹€ν–‰ μ „ : λ’€μ—μ„œ ν•„λ“œ μ΄ˆκΈ°ν™”. final ν•„λ“œμ— 유용.

Person(this.name, this.age) : birthDate = DateTime.now().subtract(Duration(days: 365 * age)); Person.custom(String userName, int userAge) : name = userName.toUpperCase(), age = userAge > 0 ? userAge : 0, birthDate = DateTime.now().subtract(Duration(days: 365 * userAge));

3-4. μƒμˆ˜ μƒμ„±μž (Const Constructor)

λΆˆλ³€ 객체. 동일 κ°’μ˜ const μΈμŠ€ν„΄μŠ€λŠ” 같은 객체λ₯Ό μ°Έμ‘°.

class ImmutablePoint { final int x; final int y; const ImmutablePoint(this.x, this.y); } var p1 = const ImmutablePoint(1, 2); var p2 = const ImmutablePoint(1, 2); print(identical(p1, p2)); // true

3-5. λ¦¬λ‹€μ΄λ ‰νŒ… μƒμ„±μž (Redirecting)

: this(...)둜 λ‹€λ₯Έ μƒμ„±μžμ— μœ„μž„.

Person.adult(String name) : this(name, 18); Person.child(String name) : this(name, 10); Person.fromJson(Map<String, dynamic> json) : this(json['name'] as String, json['age'] as int);

4. μƒμ„±μž 비ꡐ ν…Œμ΄λΈ”

μ’…λ₯˜λ¬Έλ²•μš©λ„
κΈ°λ³ΈPerson(this.name)μžλ™ μ΄ˆκΈ°ν™”
이름 μžˆλŠ”Person.guest()μ—¬λŸ¬ μ΄ˆκΈ°ν™”
μ΄ˆκΈ°ν™” 리슀트: birthDate = ...νŒŒμƒκ°’/final
μƒμˆ˜const Person()λΆˆλ³€ 객체
λ¦¬λ‹€μ΄λ ‰νŒ…: this(name, 18)μƒμ„±μž μœ„μž„
νŒ©ν† λ¦¬factory Logger(name)캐싱/싱글톀

5. νŒ©ν† λ¦¬ μƒμ„±μž (Factory Constructor)

5-1. 캐싱 β€” Logger

class Logger { final String name; static final Map<String, Logger> _cache = {}; Logger._internal(this.name); factory Logger(String name) { return _cache.putIfAbsent(name, () => Logger._internal(name)); } } final l1 = Logger('UI'); final l2 = Logger('UI'); print(identical(l1, l2)); // true

5-2. ν•˜μœ„ 클래슀 λ°˜ν™˜ β€” Shape

abstract class Shape { factory Shape(String type) { switch (type) { case 'circle': return Circle(10); case 'rectangle': return Rectangle(10, 20); default: throw ArgumentError('μ§€μ›ν•˜μ§€ μ•ŠλŠ” λ„ν˜•: $type'); } } double get area; } class Circle implements Shape { final double radius; Circle(this.radius); @override double get area => 3.14 * radius * radius; } class Rectangle implements Shape { final double width, height; Rectangle(this.width, this.height); @override double get area => width * height; }

5-3. fromJson β€” User

Flutter API 응닡 λͺ¨λΈμ— ν•„μˆ˜ νŒ¨ν„΄.

class User { final String name; final int age; final String email; User(this.name, this.age, this.email); factory User.fromJson(Map<String, dynamic> json) { return User(json['name'] as String, json['age'] as int, json['email'] as String); } Map<String, dynamic> toJson() => {'name': name, 'age': age, 'email': email}; }

6. 정적 멀버 (Static)

class MathUtils { static const double PI = 3.14159; static int calculationCount = 0; static double square(double num) { calculationCount++; return num * num; } } print(MathUtils.PI); print(MathUtils.square(5)); // 25.0

7. 좔상 클래슀

abstract class Animal { String name; Animal(this.name); void makeSound(); void sleep() { print('$name is sleeping'); } } class Dog extends Animal { Dog(String name) : super(name); @override void makeSound() { print('$name says Woof!'); } }

8. μΈν„°νŽ˜μ΄μŠ€ (implements)

DartλŠ” 별도 interface ν‚€μ›Œλ“œ 없이, λͺ¨λ“  ν΄λž˜μŠ€κ°€ μΈν„°νŽ˜μ΄μŠ€. implements μ‹œ λͺ¨λ“  멀버 μž¬μ •μ˜ ν•„μˆ˜.

class Car implements Vehicle { @override void move() { print('Car is driving'); } @override void stop() { print('Car stopped'); } } Vehicle vehicle = Car(); vehicle.move(); // λ‹€ν˜•μ„±

9. 상속 (extends)

class Student extends Person { String school; Student(String name, int age, this.school) : super(name, age); @override void introduce() { super.introduce(); print('μ €λŠ” $school에 λ‹€λ‹ˆκ³  μžˆμŠ΅λ‹ˆλ‹€.'); } }

10. Mixin (with)

κΉŠμ€ 상속 없이 κΈ°λŠ₯ μž¬μ‚¬μš©. with둜 닀쀑 Mixin 적용.

mixin Swimming { void swim() { print('수영 쀑'); } } mixin Flying { void fly() { print('λΉ„ν–‰ 쀑'); } } class Duck extends Animal with Swimming, Flying { Duck(String name) : super(name); } final duck = Duck('였리'); duck.swim(); duck.fly();

mixin CanFly on Bird β€” νŠΉμ • ν΄λž˜μŠ€μ—μ„œλ§Œ μ‚¬μš© κ°€λŠ₯ν•˜λ„λ‘ μ œν•œ

11. extends vs implements vs with

ν‚€μ›Œλ“œλ‹€μ€‘κ΅¬ν˜„ μƒμ†μš©λ„
extends단일Ois-a 상속
implements닀쀑XμΈν„°νŽ˜μ΄μŠ€
with닀쀑OκΈ°λŠ₯ μ‘°ν•©

12. Named Parameters

class Person { String name; int age; String? address; Person({required this.name, required this.age, this.address}); } final p = Person(name: '홍길동', age: 30);

13. μ—°μ‚°μž μ˜€λ²„λ‘œλ”©

class Vector { final double x, y; const Vector(this.x, this.y); Vector operator +(Vector o) => Vector(x + o.x, y + o.y); @override bool operator ==(Object o) { if (identical(this, o)) return true; return o is Vector && o.x == x && o.y == y; } @override int get hashCode => x.hashCode ^ y.hashCode; } print(Vector(1,2) + Vector(3,4)); // Vector(4,6) print(Vector(1,2) == Vector(1,2)); // true

핡심 정리

  • Private β€” _ 접두사, getter둜 λ…ΈμΆœ
  • μƒμ„±μž 5μ’… β€” κΈ°λ³Έ/이름/μ΄ˆκΈ°ν™”λ¦¬μŠ€νŠΈ/μƒμˆ˜/λ¦¬λ‹€μ΄λ ‰νŒ…
  • νŒ©ν† λ¦¬ β€” 캐싱, ν•˜μœ„ν΄λž˜μŠ€ λ°˜ν™˜, fromJson
  • 상속 β€” extends/implements/with
  • μ—°μ‚°μž μ˜€λ²„λ‘œλ”© β€” operator +/==

Implementation Steps

1

Basic constructor β€” Person(this.name, this.age) shorthand auto-initializes fields

2

Factory constructor β€” factory keyword for caching/singleton/fromJson/conditional subclass return

3

Mixin β€” combine multiple features with keyword, class Duck extends Animal with Swimming, Flying

4

abstract class β€” define abstract methods, force implementation in subclasses, also serves as interface

Pros

  • Mixin safely leverages multiple inheritance benefits
  • Factory constructors enable flexible object creation patterns

Cons

  • 5 constructor types may overwhelm beginners

Use Cases

Using factory fromJson() pattern in API response models Reusing common features (animation, gestures) with Mixin in Flutter widgets