Extension Types에 대한 다음 설명은, Dart 공식 사이트의 내용(아래의 출처 참조)을 기반으로, 독자의 이해를 돕기 위한 추가적인 글을 포함하거나, 출처의 글을 수정하는 방식으로 작성하였습니다.
Extension Types은 특정 Type A에 대한 기능 확장이 필요하지만, 성능 저하를 바라지 않는 목적에서 사용합니다. 아래의 예시를 보면, int 타입에 대한 Extension Types의 동작을 볼 수 있습니다.
extension type Wrapper(int i) {
void showValue() {
print('my value is $i');
}
}
void main() {
final wrapper = Wrapper(42);
wrapper.showValue(); // Prints 'my value is 42'
}
이 코드의 수행 결과는 다음과 같습니다.
my value is 42
코드에서 extension type은 Wrapper 입니다. main()를 보면, 일반적인 Dart 언어의 데이터 타입과 동일하게 동작하는 것을 볼 수 있습니다. 코드에서는 Wrapper 클래스의 객체가 생성되는 것으로 보이지만, 사실 내부적으로 만들어지는 것은 int 클래스의 객체 입니다. 기존 객체의 기능을 확장 하지만, 이를 위한 성능적인 부분의 저하는 없다고 합니다. 즉, wrapper가 int를 indirect 하기는 비용(cost)가 없다고 합니다. 따라서, 기존 타입에 새로운 기능을 추가함과 동시에, 기존 타입이 직접적으로 노출되는 것을 피해야 하는 경우 사용합니다.
아래의 예시를 보면, 기존 타입에 새로운 이름을 부여한 후, 추가적인 기능(+)를 포함하되, 기존 기능(isEven)을 억제하는 효과를 보여줍니다.
extension type Meters(int value) {
String get label => '${value}m';
Meters operator +(Meters other) => Meters(value + other.value);
}
void main() {
var m = Meters(42); // Has type `Meters`.
var m2 = m + m; // OK, type `Meters`.
// int i = m; // Compile-time error, wrong type.
// m.isEven; // Compile-time error, no such member.
assert(identical(m, m.value)); // Succeeds.
}
Meters 타입이 int 클래스의 extension type이지만, int 객체에 Meters 객체를 저장하는 행위와 int 클래스의 isEven이 Meters에서 동작하지 않는 것을 볼 수 있습니다. 하지만, Meters 타입은 여전히 int 타입과 같은 타입으로 인식되는 것도 assert() 구문을 통해서 볼 수 있습니다.
[출처] https://dart.dev/language/patterns
[출처] https://dart.dev/guides/language/evolution#changes-in-each-release