1. final class 기본 개념
▪️클래스의 확장(상속) 제한
- final class를 사용하면 다른 클래스가 해당 클래스를 상속하여 기능을 변경하는 것을 방지할 수 있음.
- extends, implement, 또는 mixin으로 사용이 불가능
▪️ 보안성 및 안정성 증가
- 라이브러리나 패키지를 만들 때 외부에서 임의로 상속하여 오작동하는 것을 방지할 수 있음.
▪️ 불필요한 상속 구조 제거
- 특정 클래스가 상속을 필요로 하지 않는 경우 final class를 사용하여 명확한 설계를 유도할 수 있음.
final class Animal {
void makeSound() => print("Animal sound");
}
// ❌ 오류 발생: final class는 상속할 수 없음
class Dog extends Animal {
void bark() => print("Woof!");
}
void main() {
Animal().makeSound();
}
// => Error: The class 'Animal' can't be extended because it's final.
- final class Animal은 Dog이 상속할 수 없음.
- 인스턴스화(객체 생성)는 가능하지만, 확장은 불가능.
2. base class 기본 개념
▪️ 강제적인 상속 규칙 유지
- 특정 클래스를 상속할 수 있지만, 반드시 base 키워드를 사용하도록 제한하여 예측 가능한 구조 유지.
=> extends는 가능하지만 implement는 불가능
▪️ 라이브러리 및 패키지에서 상속 방식 제한
- Dart 라이브러리 개발 시, API를 설계할 때 무분별한 상속을 방지하면서도 상속 가능성을 유지할 수 있음.
▪️ 안정적인 상속 구조 제공
- base를 사용하면 다른 개발자가 클래스의 상속 구조를 변경하는 것을 방지하면서도, 확장 가능한 방식으로 설계를 유지할 수 있습니다.
base class Animal {
void makeSound() => print("Animal sound");
}
// ✅ 올바른 상속 (같은 파일 또는 다른 파일에서도 base 키워드를 사용해야 함)
base class Dog extends Animal {
void bark() => print("Woof!");
}
void main() {
Dog dog = Dog();
dog.makeSound(); // Animal sound
dog.bark(); // Woof!
}
// => Error: The class 'Dog' must be 'base' because it extends 'Animal'.
- base class Animal을 상속하려면 base 키워드를 필수적으로 사용해야 함.
- class Dog extends Animal {} 형태로 선언하면 오류 발생.
3. interface class 기본 개념
Dart에서 interface는 클래스가 특정 메서드와 프로퍼티를 반드시 구현하도록 강제하는 역할을 합니다.
Dart에는 interface 키워드가 없지만, 모든 클래스는 자동으로 인터페이스 역할을 할 수 있습니다.
즉, Dart에서는 일반 클래스도 인터페이스처럼 사용 가능하며, implements 키워드를 사용하여 인터페이스를 구현할 수 있습니다.
- implements 키워드를 사용하여 인터페이스를 구현할 수 있음.
- 인터페이스를 구현하는 클래스는 반드시 모든 메서드를 재정의(override)해야 함.
- 다중 인터페이스 구현 가능 (여러 개의 클래스를 implements로 동시에 사용할 수 있음).
class Animal {
void makeSound() => print("Some animal sound");
}
// ✅ Animal을 인터페이스로 사용
class Dog implements Animal {
@override
void makeSound() {
print("Woof!");
}
}
void main() {
Dog dog = Dog();
dog.makeSound(); // Woof!
}
// Dart 3.0
interface class Vehicle {
void move();
}
// ✅ 모든 메서드를 반드시 재정의해야 함
class Car implements Vehicle {
@override
void move() {
print("Car is moving");
}
}
void main() {
Car car = Car();
car.move(); // Car is moving
}
- Dog 클래스는 Animal의 모든 메서드를 반드시 재정의해야 함.
4. abstract class 기본 개념
Dart에서는 abstract class를 활용하여 인터페이스를 명확하게 정의할 수 있습니다.
abstract class Animal {
void makeSound(); // 추상 메서드 (구현 필요)
}
// ✅ Animal 인터페이스 구현
class Cat implements Animal {
@override
void makeSound() {
print("Meow!");
}
}
void main() {
Cat cat = Cat();
cat.makeSound(); // Meow!
}
- abstract class Animal을 인터페이스처럼 활용.
- Cat 클래스는 makeSound()를 반드시 구현해야 함.
5. sealed class 기본 개념
Dart 3.0에서 도입된 sealed class는 같은 파일 내에서만 상속할 수 있는 클래스입니다.
즉, 다른 파일에서는 sealed class를 상속할 수 없으며, 상속을 허용하면서도 제한적인 확장을 제공하는 기능입니다.
sealed class Animal {} // ✅ sealed class 선언
// ✅ 같은 파일 내에서만 상속 가능
class Dog extends Animal {}
class Cat extends Animal {}
// ❌ 다른 파일에서는 상속할 수 없음!
// switch 문 예제
sealed class PaymentMethod {}
class CreditCard extends PaymentMethod {}
class PayPal extends PaymentMethod {}
class BankTransfer extends PaymentMethod {}
void processPayment(PaymentMethod payment) {
switch (payment) {
case CreditCard():
print("Processing credit card payment");
case PayPal():
print("Processing PayPal payment");
case BankTransfer():
print("Processing bank transfer payment");
}
}
void main() {
processPayment(CreditCard()); // Processing credit card payment
}
- sealed class는 같은 파일 내에서만 상속 가능. (하위 클래스는 제한적, switch문과 함께 사용하기 좋)
- 다른 파일에서는 상속이 불가능, 즉, 특정 파일 안에서만 클래스를 확장할 수 있도록 제한.
- sealed class를 사용하면 switch 문에서 모든 하위 클래스를 체크해야 하므로, 새로운 하위 클래스가 추가될 경우 컴파일러가 자동으로 누락된 case를 감지할 수 있음.
6. mixin class 기본 개념
Dart에서 mixin은 코드를 여러 클래스에서 재사용할 수 있도록 하는 기능입니다.
mixin을 사용하면 클래스를 상속하지 않고도 특정 기능을 여러 클래스에서 공유할 수 있습니다.
- mixin은 클래스를 상속하지 않고 기능을 공유하는 방법입니다.
- with 키워드를 사용하여 mixin을 적용할 수 있습니다.
- 다중 상속이 불가능한 Dart에서 mixin을 활용하면 코드 중복 없이 여러 클래스에서 같은 기능을 사용할 수 있습니다.
mixin Logger {
void log(String message) {
print("LOG: $message");
}
}
class Service with Logger {
void fetchData() {
log("Fetching data...");
}
}
void main() {
Service service = Service();
service.fetchData(); // LOG: Fetching data...
}
// 다중 적용
mixin Logger {
void log(String message) => print("LOG: $message");
}
mixin Validator {
bool isValid(String input) => input.isNotEmpty;
}
class Service with Logger, Validator {
void fetchData(String data) {
if (isValid(data)) {
log("Fetching data: $data");
} else {
log("Invalid data");
}
}
}
void main() {
Service service = Service();
service.fetchData("Hello"); // ✅ LOG: Fetching data: Hello
service.fetchData(""); // ✅ LOG: Invalid data
}
- mixin Logger를 정의하고 log 메서드를 포함.
- Service 클래스에서 Logger를 with 키워드로 포함.
- Service 클래스에서 log 메서드를 사용하여 로깅 기능을 추가.
| 키워드 | 설명 | 상속 가능 여부 |
| sealed class | 같은 파일 내에서만 상속 가능 | ✅ 같은 파일 내에서만 가능 |
| final class | 어디서든 상속 불가능 | ❌ 상속 불가능 |
| base class | 다른 파일에서도 상속 가능하지만, base 키워드가 필요 | ✅ base 키워드 사용 시 가능 |
'Flutter > 개념' 카테고리의 다른 글
| Dart 기본기 - Stream, await, async, yield (2) | 2025.02.05 |
|---|---|
| Dart 기본기 - Future, await, async (3) | 2025.02.05 |
| Dart 기본기 - final vs const 차이 (2) | 2025.02.03 |
| Dart 기본기 - null 사용법 (2) | 2025.02.03 |
| Dart 기본기 - dynamic vs var 차이 (2) | 2025.02.03 |
댓글