2.7 추상(Abstract)

2.7 추상(Abstract)

추상 타입은 런타임에는 실제로 다른 타입인 타입이에요. 구체 타입 "위에" 타입을 정의해 그 동작을 수정하거나 확장하는 컴파일 타임 기능입니다:

abstract AbstractInt(Int) {
  inline public function new(i:Int) {
    this = i;
  }
}

이 예제에서 다음을 알 수 있어요:

  • abstract 키워드는 추상 타입을 선언한다는 뜻이에요.
  • AbstractInt는 추상 타입의 이름이며, 타입 식별자 규칙을 따르는 아무 이름이든 될 수 있어요.
  • 기반 타입(underlying type) Int가 괄호 () 안에 있습니다.
  • 필드는 중괄호 {} 안에 있으며,
  • 여기에는 Int 타입의 인자 하나 i를 받는 생성자 함수 new가 있어요.

정의: 기반 타입(Underlying Type) — 추상의 기반 타입은 런타임에 해당 추상을 나타내는 데 사용되는 타입입니다. 보통 구체(즉 비-추상) 타입이지만, 다른 추상 타입일 수도 있어요.

문법은 클래스와 유사하며 의미론도 실제로 비슷해요. 사실 추상의 "본문"(여는 중괄호 뒤의 모든 것)은 클래스 필드로 파싱됩니다. 추상은 메서드(method) 필드와 물리적이지 않은(non-physical) 속성(property) 필드를 가질 수 있어요.

또한 추상은 클래스처럼 인스턴스화하고 사용할 수 있습니다:

class Main {
  static public function main() {
    var a = new AbstractInt(12);
    trace(a); // 12
  }
}

앞서 언급했듯 추상은 컴파일 타임 기능이므로, 위 코드가 실제로 무엇을 생성하는지 보는 것은 흥미로워요. 이에 적합한 대상은 간결하고 깨끗한 코드를 만드는 JavaScript입니다. 위 코드를 haxe --main MyAbstract --js myabstract.js로 컴파일하면 다음 JavaScript 코드가 나옵니다:

var a = 12;
console.log(a);

추상 타입 Abstract는 출력에서 완전히 사라지고, 기반 타입 Int의 값만 남아요. 이는 Abstract의 생성자가 인라인되고, 인라인된 표현식이 this에 값을 할당하기 때문이에요. 이에 대해서는 인라인(Inline) 절에서 배우게 됩니다. 클래스 관점에서 생각하면 놀랍지만, 이것은 정확히 추상의 맥락에서 표현하고 싶은 것입니다. 인라인된 멤버 메서드는 같은 방식으로 처리됩니다.

출처: Abstract

본문

추상 타입의 개념

추상 타입은 컴파일 타임에만 존재하고 런타임에는 기반 타입으로 표현되는 타입이에요. 기반 타입의 동작을 수정·확장하는 데 사용되며, 예를 들어 AbstractInt(Int)Int를 감싸면서 새 동작을 정의합니다.

추상의 구조

추상 선언은 abstract 이름(기반타입) {} 형태예요. 본문은 클래스 필드로 파싱되며, 메서드와 속성을 가질 수 있어요. 생성자 new를 정의해 인스턴스화할 수 있습니다.

런타임 표현

추상은 컴파일 타임 기능이라 생성된 코드에서 사라져요. 위 예제에서 new AbstractInt(12)trace(a)는 생성자가 인라인되어 var a = 12; console.log(a);로 바뀝니다. 즉 추상 인스턴스는 기반 타입의 값으로 그대로 표현됩니다.

더 알아보기