final 클래스 키워드
Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 40번째.
때때로 클래스가 확장되는 것을 방지하고 싶을 때가 있습니다. final 키워드를 클래스에 적용하면, 다른 클래스가 해당 클래스를 상속받는 것을 방지합니다.
final class DatabaseConnection {
String connectionString;
DatabaseConnection(this.connectionString);
void connect() {
print('Connected to $connectionString');
}
}
// 이 코드는 컴파일 타임 에러를 발생시킵니다:
// class CustomConnection extends DatabaseConnection { }클래스를 final로 표시하는 것은 이를 확장하는 것이 의도된 동작이나 보안 보장을 깨뜨릴 수 있을 때 유용합니다. 예를 들어, 민감한 리소스를 관리하는 클래스는 해당 메서드가 예기치 않은 방식으로 오버라이드되지 않도록 보장해야 할 수도 있습니다.
Dart 3는 또한 관련된 수식어들을 도입했습니다: base는 서브클래스가 (implements가 아닌) extends를 사용하도록 강제하며, sealed는 상속을 동일한 라이브러리로 제한합니다. 지금은 클래스를 완전히 잠그는 가장 간단한 방법인 final에 집중해 봅시다.
클래스 설계가 완료되었고 상속이 문제만 일으킬 것이라고 확신할 때 final 클래스를 사용하세요. 하지만 과도하게 사용하지 마세요. 대부분의 클래스는 확장을 위해 열려 있는 것이 유리합니다.
챌린지
쉬움클래스가 확장되는 것을 방지해야 하는 시점과 이유를 보여주는 보안 구성 시스템을 구축해 보겠습니다. 애플리케이션 설정을 관리하는 final 클래스를 만들어 상속을 통해 그 동작이 변경되지 않도록 보장할 것입니다.
코드를 두 개의 파일로 구성합니다:
config.dart: 여기에 구성 클래스들을 정의합니다:- 확장할 수 없는
final class AppConfig를 만듭니다.String appName과String version속성, 두 값을 모두 받는 생성자, 그리고[appName] v[version]을 출력하는display()메서드를 가져야 합니다. String name과bool enabled속성, 두 속성에 대한 생성자, 그리고[name]: [enabled ? 'ON' : 'OFF']를 출력하는status()메서드를 가진 일반(non-final)Feature클래스를 만듭니다.Feature를 확장하고String warning속성을 추가하는ExperimentalFeature클래스를 만듭니다.@override를 사용하여status()를 재정의하되, 먼저super.status()로 부모 버전을 호출한 다음Warning: [warning]을 출력합니다.
- 확장할 수 없는
main.dart: 구성 파일을 임포트하고 final 클래스와 일반 클래스의 차이점을 보여줍니다:- appName은
'MyApp', version은'2.0.1'인AppConfig를 생성한 후display()를 호출합니다. - 빈 줄을 출력합니다.
- name은
'Dark Mode', enabled는true인Feature를 생성한 후status()를 호출합니다. - 빈 줄을 출력합니다.
- name은
'AI Assistant', enabled는false, warning은'May be unstable'인ExperimentalFeature를 생성한 후status()를 호출합니다.
- appName은
AppConfig는 구성 동작이 일관되고 안전하게 유지되어야 하므로 final로 표시되었습니다. 어떤 서브클래스도 설정 관리 방식을 변경할 수 없어야 합니다. 반면, Feature는 확장이 가능하도록 열려 있어 ExperimentalFeature가 특화된 동작을 추가할 수 있습니다.
예상 출력:
MyApp v2.0.1
Dark Mode: ON
AI Assistant: OFF
Warning: May be unstable치트 시트
final 키워드는 클래스가 확장되는 것을 방지합니다:
final class DatabaseConnection {
String connectionString;
DatabaseConnection(this.connectionString);
void connect() {
print('Connected to $connectionString');
}
}
// 이 코드는 컴파일 타임 에러를 발생시킵니다:
// class CustomConnection extends DatabaseConnection { }클래스를 확장하는 것이 의도된 동작이나 보안 보장을 손상시킬 수 있는 경우 final 클래스를 사용하세요. 잠가야 할 특별한 이유가 없는 한 대부분의 클래스는 확장을 위해 열려 있어야 합니다.
Dart 3는 또한 base(하위 클래스가 extends를 사용하도록 강제함) 및 sealed(상속을 동일한 라이브러리로 제한함) 수식어를 제공합니다.
직접 해보기
import 'config.dart';
void main() {
// TODO: appName이 'MyApp'이고 version이 '2.0.1'인 AppConfig를 생성하세요
// 그 다음 display()를 호출하세요
// TODO: 빈 줄을 출력하세요
// TODO: name이 'Dark Mode'이고 enabled가 true인 Feature를 생성하세요
// 그 다음 status()를 호출하세요
// TODO: 빈 줄을 출력하세요
// TODO: name이 'AI Assistant'이고,
// enabled가 false이며 warning이 'May be unstable'인 ExperimentalFeature를 생성하세요
// 그 다음 status()를 호출하세요
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.