[Flutter]Sealed Class

메모하는 개발자·2022년 3월 13일
1

Flutter메모

목록 보기
1/7

Sealed Class란?

Enum 클래스의 확장판이라고 생각하면 쉽다.
가장 큰 차이점은 Enum은 하나의 인스턴스만 사용할 수 있고 생성자도 동일하지만
Sealed Class는 state(상태값)을 포함한 여러 인스턴스를 가질 수 있고 생성자도 다르게 가질 수 있다.

Sealed Class 쓰는 이유?

  1. Pattern matching구조(Switch, if-else)에서
    새로운 타입이 추가됐을때 혹은 타입이 누락됐을때 컴파일러에서 자식 클래스(지정해준 타입들)을 알고있어서 에러 가능성을 확 잡아줄 수 있다!

  2. Sealed Class는 state(상태값)을 포함한 여러 인스턴스를 가질 수 있고 생성자도 다르게 가질 수 있다.

예를들어 어떻게 활용될 수 있을까?

앱을 만들때 여러 뷰타입을 지정해놓고 컴포넌트를 만드는 경우가 있다.
각 뷰타입마다 파라미터가 달라질 수 있는데 Enum의 경우 불가하지만
sealed 클래스를 쓰면 아래 예시처럼 가능하다.
또한, 뷰타입이 많아졌을때 pattern matching구조에서 누락된 뷰타입이나 잘못된 뷰타입을 잡아줄 수 있다.

enum class ViewType 
{ 
PRD1, 
PRD2(val prdid), // Enum은 생성자가 동일. 이런 형태는 불가함.
}
sealed class ViewType
{ 
data class PRD1(val prdId: Int) 
data class PRD2(val prdNm: String) 
}

어떻게 쓸까?

[패키지]
https://pub.dev/packages/sealed_unions

[참고]
https://resocoder.com/2019/09/16/sealed-unions-in-dart-never-write-an-if-statement-again-kind-of/

[요약]
WeatherInitial,
WeatherLoading,
WeatherLoaded,
세가지 상태에 대해 Sealed Class사용여부에 따른 차이점을 보면

  1. Sealed Class를 사용하지 않았을 경우
  • 각 상태마다 처리를 if문으로 작성해줘야 한다.
String widgetBuilder(WeatherState state) {
  if (state is WeatherInitial) {
    return "Some initial widget";
  } else if (state is WeatherLoading) {
    return "Circular progress indicator";
  } else if (state is WeatherLoaded) {
    return "The temperature is ${state.temperature}";
  }
}
  1. Sealed Class를 사용한 경우
  • boilerplate 코드가 있다.
  • if, switch문에서 누락된 타입이나 신규 추가 타입에 대한 에러를 잡아준다.
class WeatherState
    extends Union3Impl<_WeatherInitial, _WeatherLoading, _WeatherLoaded> {
 
  static final Triplet<_WeatherInitial, _WeatherLoading, _WeatherLoaded>
      _factory =
      const Triplet<_WeatherInitial, _WeatherLoading, _WeatherLoaded>();

  states
  WeatherState._(
    Union3<_WeatherInitial, _WeatherLoading, _WeatherLoaded> union,
  ) : super(union);

  classes
  factory WeatherState.initial() =>
      WeatherState._(_factory.first(_WeatherInitial()));

  factory WeatherState.loading() =>
      WeatherState._(_factory.second(_WeatherLoading()));

  factory WeatherState.loaded(int temperature) =>
      WeatherState._(_factory.third(_WeatherLoaded(temperature)));
}

class _WeatherInitial {}

class _WeatherLoading {}

class _WeatherLoaded {
  final int temperature;

  _WeatherLoaded(this.temperature);
}
String widgetBuilder(WeatherState state) {
  return state.join(
    (initial) => "Some initial widget",
    (loading) => "Circular progress indicator",
    (loaded) => "The temperature is ${loaded.temperature}",
  );
}

0개의 댓글