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)); // true3-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)); // true5-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.07. μΆμ ν΄λμ€
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 | λ¨μΌ | O | is-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
Basic constructor β Person(this.name, this.age) shorthand auto-initializes fields
Factory constructor β factory keyword for caching/singleton/fromJson/conditional subclass return
Mixin β combine multiple features with keyword, class Duck extends Animal with Swimming, Flying
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