5

JavaScript 객체가 Google Closure inheritance mechanism을 사용하는 인터페이스 구현인지 어떻게 테스트 할 수 있습니까?Google 클로저 클래스 프레임 워크에서 객체가 인터페이스 구현인지 테스트합니다.


나는 작동하지 않았다 new my.Dog()object instanceof my.Animal 통해 생성 된 오브젝트의 my.Animal의 힌트를 찾을 수 없습니다. 인터페이스에 대한 유일한 정보는 자식 클래스에 메서드를 구현하는 것을 잊어 버리는 경우 컴파일러 오류입니다. 내가 찾은

/** 
* @interface 
*/ 
my.Animal = function() {}; 

/** 
* Does something. 
* @return {string} 
*/ 
my.Animal.prototype.doSomething; 

/** 
* @constructor 
* @implements {my.Animal} 
*/ 
my.Dog = function() {}; 

/** @inheritDoc */ 
my.Dog.prototype.doSomething() = function { 
    return "something"; 
} 

var dog = new my.Dog(); 
console.log(dog instanceof my.Animal); // returns false 

방법 중 하나는 너무 많은 측면에서 나쁜 불구하고, 인터페이스의 속성에 대한 약 테스트하는 것입니다 :

console.log(!!dog.doSomething); // returns true 
+2

나는 downvoted하기 전에 뭐가 잘못 됐는지에 대한 의견을 듣고 싶습니다. –

답변

2

@interface은 순전히 유형 검사기 구성입니다. 컴파일되지 않은 코드에는 런타임 검사를 위해 배선을 추가하기 위해 @interface/@implements에 대한 설명을 검사 할 수있는 것이 없습니다. Closure의 목표는 컴파일 전후에 코드가 동일하게 실행된다는 것입니다 (사용중인 최적화 모드에 대한 제한 사항을 준수한다고 가정). 당신이 어디에 표시되지 않도록이 조금 짜증나는 다음

my.Dog.prototype.implements_my_Animal = true; 

if (foo.implements_my_Animal) ... 

: 런타임 검사가 요구되는 전형적인 패턴에 관심이 인터페이스를 구현하는 클래스를 태그하는 것입니다 그것은 필요하지 않습니다. 이 방법에는 여러 가지가 있습니다. 그러나 ADVANCED 모드를 사용하면 대부분 구현 클래스 (예제의 my.Dog)는 이스케이프 처리되고 사용되지 않으면 제거되지 않습니다.

+0

주 : true 대신에 센티넬 객체를 추가하고'(foo.implements_my_Animal === the_object) '와 같은 동등성을 검사해야합니다. 그렇지 않으면 객체가 동일한 키를 정의 할 때 오탐 (false positives)을 얻게 될 것이기 때문입니다. 이것은 foo.a와 같은 것으로 이름을 변경하는 사전 컴파일 후에 쉽게 발생할 수 있습니다. 이것은 우리가 Clojurescript에서 만난 것입니다 : https://dev.clojure.org/jira/browse/CLJS-1658 – ClojureMostly

1

당신이 직접 할 수 없습니다.

클로저 컴파일러 유형 시스템에서 @extends은 상속에 사용되며 instanceof 테스트와 관련됩니다. @implements으로 표시된 인터페이스 구현은 엄격하게 컴파일 타임 검사입니다. 그들은 당신의 객체가 인터페이스의 정의와 일치하는 메소드와 속성을 포함한다는 약속입니다.

이와 같이 런타임에 포괄적 인 방식으로 테스트하기 위해 인터페이스의 각 속성의 존재 여부와 유형을 확인해야합니다.