반응형
Jake Seo
제이크서 위키 블로그
Jake Seo
전체 방문자
오늘
어제
  • 분류 전체보기 (715)
    • 일상, 일기 (0)
    • 백준 문제풀이 (1)
    • 릿코드 문제풀이 (2)
    • 알고리즘 이론 (10)
      • 기본 이론 (2)
      • 배열과 문자열 (8)
    • 데이터베이스 (15)
      • Planet Scale (1)
      • MSSQL (9)
      • 디비 기본 개념 (1)
      • SQLite 직접 만들어보기 (4)
    • 보안 (7)
    • 설계 (1)
    • 네트워크 (17)
      • HTTP (9)
      • OSI Layers (5)
    • 회고 (31)
      • 연간 회고 (2)
      • 주간 회고 (29)
    • 인프라 (52)
      • 도커 (12)
      • AWS (9)
      • 용어 (21)
      • 웹 성능 (1)
      • 대규모 서비스를 지탱하는 기술 (9)
    • 깃 (7)
    • 빌드 도구 (7)
      • 메이븐 (6)
      • 그레이들 (0)
    • Java (135)
      • 이펙티브 자바 (73)
      • 자바 API (4)
      • 자바 잡지식 (30)
      • 자바 디자인 패턴 (21)
      • 톰캣 (Tomcat) (7)
    • 프레임워크 (64)
      • next.js (14)
      • 스프링 프레임워크 (28)
      • 토비의 스프링 (6)
      • 스프링 부트 (3)
      • JPA (Java Persistence API) (5)
      • Nest.js (8)
    • 프론트엔드 (48)
      • 다크모드 (1)
      • 노드 패키지 관리 매니저 (3)
      • CSS (19)
      • Web API (11)
      • tailwind-css (1)
      • React (5)
      • React 새 공식문서 요약 (1)
      • HTML (Markup Language) (5)
    • 자바스크립트 (108)
      • 모던 자바스크립트 (31)
      • 개념 (31)
      • 정규표현식 (5)
      • 코드 스니펫 (1)
      • 라이브러리 (6)
      • 인터뷰 (24)
      • 웹개발자를 위한 자바스크립트의 모든 것 (6)
      • 팁 (2)
    • Typescript (49)
    • 리눅스와 유닉스 (10)
    • Computer Science (1)
      • Compiler (1)
    • IDE (3)
      • VSCODE (1)
      • IntelliJ (2)
    • 세미나 & 컨퍼런스 (1)
    • 용어 (개발용어) (16)
      • 함수형 프로그래밍 용어들 (1)
    • ORM (2)
      • Prisma (2)
    • NODEJS (2)
    • cypress (1)
    • 리액트 네이티브 (React Native) (31)
    • 러스트 (Rust) (15)
    • 코틀린 (Kotlin) (4)
      • 자바에서 코틀린으로 (4)
    • 정규표현식 (3)
    • 구글 애널리틱스 (GA) (1)
    • SEO (2)
    • UML (2)
    • 맛탐험 (2)
    • 리팩토링 (1)
    • 서평 (2)
    • 소프트웨어 공학 (18)
      • 테스팅 (16)
      • 개발 프로세스 (1)
    • 교육학 (1)
    • 삶의 지혜, 통찰 (1)
    • Chat GPT (2)
    • 쉘스크립트 (1)
    • 컴파일 (2)
    • Dart (12)
    • 코드팩토리의 플러터 프로그래밍 (4)
    • 플러터 (17)
    • 안드로이드 스튜디오 (1)
    • 윈도우즈 (1)
    • 잡다한 백엔드 지식 (1)
    • 디자인 패턴 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 슬로우 쿼리
  • next js app
  • 자바스크립트 면접
  • 자바 검증
  • 이펙티브 자바
  • 싱글톤 패턴
  • Next.js
  • 자바스크립트 인터뷰
  • item9
  • 느린 쿼리
  • 이펙티브자바
  • 스프링 검증
  • 자바스크립트
  • rust
  • 메이븐 라이프사이클
  • item8
  • 자바 디자인패턴
  • try-with-resources
  • NEXT JS
  • 싱글턴
  • 프로그래머의 뇌
  • 싱글톤
  • 작업기억공간
  • 객체복사
  • 메이븐 골
  • 자료구조
  • 도커공식문서
  • 알고리즘
  • Pre-rendering
  • 서버리스 컴퓨팅
  • 플라이웨이트패턴
  • serverless computing
  • 추상 팩터리 패턴
  • 팩터리 메서드 패턴
  • 자바
  • Javadoc 자바독 자바주석 주석 Comment
  • bean Validation
  • item7
  • 이펙티브 자바 item9
  • 빈 검증
  • 메이븐 페이즈
  • 러스트
  • MSSQL
  • prerendering
  • 참조 해제
  • Java
  • 디자인패턴
  • 토비의 스프링
  • pnpm
  • 외래키 제약조건

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Jake Seo

제이크서 위키 블로그

Dart

다트(Dart) 언어의 클래스 제어자 (Class modifier) 정리

2023. 10. 12. 01:25

클래스 제어자 혹은 수정자 (class modifier)

  • 클래스 혹은 믹스인이 자체 라이브러리 내 혹은 정의된 라이브러리 외부에서 사용되는 방식을 제어한다.
  • 제어자 키워드는 클래스 혹은 믹스인 선언 앞에 온다.
    • 이를테면, abstract class 는 추상 클래스를 정의한다.

class 앞에 올 수 있는 것들

  • abstract

  • base

  • final

  • interface

  • sealed

  • mixin

  • base 만 믹스인 선언 전에 올 수 있다. 제어자들은 enum, typedef, extension 과 같은 다른 선언에 적용할 수 없다.

  • 클래스 제어자 사용 여부는 클래스의 의도된 용도와 클래스가 의존할 수 있어야 하는 동작을 고려해야 한다.

제어자 없음

  • 어떤 라이브러리에서든 생성자나 하위 타입에 대한 권한을 제한하고 싶지 않다면, 제어자 없이 class 나 mixin 을 사용하면 된다.
  • 기본적으로 아래와 같은 동작이 가능하다.
    • 클래스의 새 인스턴스를 생성
    • 새 하위 타입을 만들기 위해 클래스를 확장 (extend)
    • 클래스 혹은 믹스인의 인터페이스를 구현
    • 믹스인 혹은 믹스인 클래스에서 믹스

abstract

  • 전체 인터페이스의 구체적인 구현이 필요 없는 클래스를 정의할 때 abstract 제어자를 사용한다.
  • 추상 클래스는 어떤 라이브러리에서도 생성(construct)이 불가능하다.
  • 추상 클래스는 종종 추상 메서드를 갖는다.
  • 추상 클래스를 인스턴스화할 수 있는 것처럼 보이게 하려면 팩토리 생성자를 정의해야 한다.
// Library a.dart
abstract class Vehicle {
  void moveForward(int meters);
}
// Library b.dart
import 'a.dart';

// Error: 추상 클래스 자체를 생성하는 것은 불가능하다.
Vehicle myVehicle = Vehicle();

// 추상 클래스는 클래스 확장(extend)이 가능하다.
class Car extends Vehicle {
  int passengers = 4;
  // ···
}

//t
class MockVehicle implements Vehicle {
  @override
  void moveForward(int meters) {
    // ...
  }
}

base

  • 클래스 혹은 믹스인 구현의 상속을 강제한다.
  • 자체 라이브러리의 외부 구현을 허용하지 않는다.
  • 보장되는 것들:
    • base 클래스의 생성자는 클래스의 하위 타입의 인스턴스가 생성될 때마다 호출된다.
    • 구현된 모든 비공개 멤버가 서브타입에 존재한다.
    • 모든 서브타입이 새 멤버를 상속하므로, 베이스 클래스에서 새로 구현된 멤버는 서브타입을 손상시키지 않는다.
      • 하위 타입이 이미 동일한 이름과 호환되지 않는 시그니쳐를 가진 멤버를 선언하지 않는 한 참이다.
  • base 클래스를 구현하거나 확장하는 모든 클래스는 base, final, sealed 로 표시해야 한다.
    • 외부 클래스가 base 클래스가 보장하는 것들을 위반하는 것을 방지할 수 있다.
// Library a.dart
base class Vehicle {
  void moveForward(int meters) {
    // ...
  }
}
// Library b.dart
import 'a.dart';

// 생성 가능
Vehicle myVehicle = Vehicle();

// 확장 가능
base class Car extends Vehicle {
  int passengers = 4;
  // ...
}

// ERROR: 구현의 상속이 강제됐기 때문에 오버라이드 할 수 없다.
base class MockVehicle implements Vehicle {
  @override
  void moveForward() {
    // ...
  }
}

interface

  • 인터페이스를 정의하기 위해 사용한다.
  • 외부 라이브러리는 인터페이스를 구현할 수는 있지만 확장할 수는 없다.
  • 보장되는 것들:
    • 클래스 인스턴스 메서드 중 하나가 다른 인스턴스 메서드를 호출하면 항상 동일한 라이브러리에서 알려진 메서드 구현을 호출한다.
    • 다른 라이브러리는 인터페이스 클래스의 자체 메서드가 나중에 예상치 못하게 호출할 수 있는 메서드를 재정의할 수 없다.
      • 이건 fragile base class 문제 를 줄이는데 도움이 된다.
// Library a.dart
interface class Vehicle {
  void moveForward(int meters) {
    // ...
  }
}
// Library b.dart
import 'a.dart';

// 생성 가능
Vehicle myVehicle = Vehicle();

// ERROR: 인터페이스를 상속받을 수 없다
class Car extends Vehicle {
  int passengers = 4;
  // ...
}

// 인터페이스를 구현하는 것은 가능
class MockVehicle implements Vehicle {
  @override
  void moveForward(int meters) {
    // ...
  }
}

abstract interface

  • interface 제어자의 가장 흔한 용례다.
  • 순수한 인터페이스를 정의하기 위해 사용된다.
  • interface 와 abstract 제어자를 합쳐서(Combine) abstract interface class 를 만든다.
  • interface 클래스 같이, 구현은 가능한데, 상속은 불가능하다. 순수한 인터페이스가 된다.
  • abstract 클래스 같이, 순수한 인터페이스는 추상적인 멤버를 가질 수 있다.

final

  • 계층 구조를 닫는다.
  • 현재 라이브러리 외부 클래스에서 하위 타입을 만드는 것을 방지할 수 있다.
  • 상속과 구현을 막는다.
  • 보장되는 것들:
    • API 에 증분적인 변화가 가능하다.
    • 서드파티 서브 클래스에서 덮어씌워지지 않았다는 것을 알고 인스턴스 메서드를 호출할 수 있다.
  • final 클래스는 같은 라이브러리 내에서 확장되거나 구현될 수 있다.
  • final 제어자는 base 의 효과를 포함한다.
    • 모든 하위 클래스에도 base, final, sealed 로 표시되어 있어야 한다.
// Library a.dart
final class Vehicle {
  void moveForward(int meters) {
    // ...
  }
}
// Library b.dart
import 'a.dart';

// Can be constructed
Vehicle myVehicle = Vehicle();

// ERROR: 상속 불가
class Car extends Vehicle {
  int passengers = 4;
  // ...
}

class MockVehicle implements Vehicle {
  // ERROR: 구현 불가
  @override
  void moveForward(int meters) {
    // ...
  }
}

sealed

  • 하위타입의 enumerable 한 집합을 만들려면 sealed 제어자를 사용한다.
  • 정적으로 완전한 하위 유형에 대한 스위치를 만들 수 있다.
  • sealed 제어자는 라이브러리 외부에서 클래스가 확장되거나 구현되는 것을 막는다.
  • sealed 클래스는 묵시적으로 abstract 이다.
    • 생성이 불가능하다.
    • factory 생성자를 가질 수 있다.
    • 하위 클래스가 사용할 생성자를 만들 수 있다.
  • sealed 클래스의 하위 클래스는 묵시적으로 추상적이지 않다.
  • 같은 라이브러리에만 존재할 수 있기 때문에, 컴파일러는 어떤 직접 접근 가능한 하위타입들을 안다.
  • 컴파일러는 스위치가 가능한 모든 하위 타입을 완전히 처리하지 못할 때 사용자에게 경고를 표시할 수 있다.
sealed class Vehicle {}

class Car extends Vehicle {}

class Truck implements Vehicle {}

class Bicycle extends Vehicle {}

// ERROR: 인스턴스화 불가능
Vehicle myVehicle = Vehicle();

// 서브 클래스는 인스턴스화 가능
Vehicle myCar = Car();

String getVehicleSound(Vehicle vehicle) {
  // ERROR: Bicycle 서브타입에 대한 케이스를 정의하거나 디폴트 케이스가 필요함
  return switch (vehicle) {
    Car() => 'vroom',
    Truck() => 'VROOOOMM',
  };
}

exhaustive switching 을 원하지 않거나 API 를 깰 필요 없이 하위 타입을 나중에 추가할 수 있기 원한다면, final 제어자를 사용하는 것이 좋다.
더 깊이 있는 비교를 원한다면, sealed versus final 을 읽어보면 좋다.

제어자 합성하기

  • 제어자를 결합할 수 있다.
  • 아래의 순서대로 사용할 수 있다.
  1. (Optional) abstract: 클래스가 abstract 멤버를 포함할지, 인스턴스화를 금지할지에 대해 기술한다.
  2. (Optional) base, interface, final, sealed 중 하나를 선택하여 다른 라이브러리에서 클래스의 하위 타입을 만드는 것을 제한할지 기술한다.
  3. (Optional) mixin: 선언이 믹스인 될 수 있을지에 대해 기술한다.
  4. class 키워드 입력
  • 모순되거나 중복되거나 상호 배타적이기 때문에 결합할 수 없는 제어자들도 있다.
    • abstract 와 sealed
      • sealed 는 항상 묵시적으로 abstract 이다.
    • interface, final, sealed 를 mixin 과 함께 사용
      • 세 접근자는 mixing in 을 금지한다.
반응형
저작자표시 비영리 (새창열림)

'Dart' 카테고리의 다른 글

다트 (Dart) 언어의 생성자 (Constructors) 정리  (0) 2023.10.13
다트(Dart) 언어의 클래스(Class) 정리  (0) 2023.10.12
다트(Dart) 언어의 확장 메서드 (Extension methods) 정리  (0) 2023.10.10
다트의 오류 처리 방식  (1) 2023.10.08
다트 (Dart) 변수, 상수 선언 방식  (0) 2023.10.08
    'Dart' 카테고리의 다른 글
    • 다트 (Dart) 언어의 생성자 (Constructors) 정리
    • 다트(Dart) 언어의 클래스(Class) 정리
    • 다트(Dart) 언어의 확장 메서드 (Extension methods) 정리
    • 다트의 오류 처리 방식
    Jake Seo
    Jake Seo
    ✔ 잘 보셨다면 광고 한번 클릭해주시면 큰 힘이 됩니다. ✔ 댓글로 틀린 부분을 지적해주시면 기분 나빠하지 않고 수정합니다. ✔ 많은 퇴고를 거친 글이 좋은 글이 된다고 생각합니다. ✔ 간결하고 명료하게 사람들을 이해 시키는 것을 목표로 합니다.

    티스토리툴바