2011-09-18 3 views
1

javascript가 생성자의 속성을 올바르게 인식하도록 Google 클로저 컴파일러를 얻는 방법을 이해할 수 없습니다. 예를 들어, 아래 코드에서 컴파일러가 다음과 같은 오류를 생성하지 않도록 27 행에서 'cls'유형을 알 수 없습니다.클로저 컴파일러에서 javascript의 생성자 속성을 올바르게 확인하는 방법

foo.js : 29 : 경고 - cls에 정의 된 적이없는 속성 cls.say(); ^

설명서를 읽으면 25시에해야하는 것처럼 보입니다. 누군가 도와 줄 수 있습니까? 감사,

1 /** 
2 * @interface 
3 **/ 
4 function Sayer() {} 
5 Sayer.prototype.say = function() {}; 
6 Sayer.say = function() {}; 
7 
8 /** 
9 * @constructor 
10 * @implements {Sayer} 
11 **/ 
12 function A() {} 
13 A.say = function() { console.log('A factory'); }; 
14 A.prototype.say = function() { console.log('Am an A'); } 
15 
16 /** 
17 * @constructor 
18 * @implements {Sayer} 
19 **/ 
20 function B() {} 
21 B.say = function() { console.log('B factory'); }; 
22 B.prototype.say = function() { console.log('Am an B'); }; 
23 
24 /** 
25 * @param {function(new:Sayer)} cls 
26 **/ 
27 function makeSayer(cls) { 
28  var obj = new cls(); 
29  cls.say(); 
30  obj.say(); 
31 } 
32 
33 makeSayer(A); 
34 makeSayer(B); 
+0

호기심에서 'new : B' 또는'new : A'로 변경하면 어떻게됩니까? 나는 그것이 인터페이스를 잘 다루지 않는지 궁금하다. 또는 인터페이스에 정적 메서드가 허용되지 않는 경우? –

+0

차이가 없습니다. 나는 Sayer에게 A와 B의 수퍼 클래스를 만들었고 구현 도구를 확장 등으로 변경했습니다. 여전히 불평합니다. – seth

답변

0

인터페이스의 "Sayer.say"는 무시됩니다.

Closure의 고급 모드를 준비 중입니까? 고급 모드에서 "A.say"및 "B.say"는 "A $ say"및 "B $ say"로 이름이 바뀌고 형식 검사에서는이를 예상하고 적절하게 그것에 대해 불평합니다 (A.say 메서드가 없습니다.).

당신은에 의해이 간접적으로 추가 붕괴 방지 할 수 있습니다

:

function addSay(sayer, fn) { 
    sayer.say = fn; 
} 

을 나는 당신과 같은 라인을 추가하여 유형의 경고를 피할 수있는 가정 :

Function.prototype.say; 

을하지만 잘 모르겠어요 너 너가 원하는거야.

당신은 번거 로움을 피하고 프로토 타입에 추가하고 대신에 호출 할 수 있습니다 :

A.prototype.classSay = function() {}; 
+0

필자는 컴파일러가 실제로 제대로 입력하지 않았 음을 알아 냈습니다. 타입 경고는 (실제로 어쨌든) 코드 작성을 정말로 저 지르지 않는 한 프로토 타입 선언을 작성함으로써 사라지지 않을 것입니다. 어쨌든 버그 보고서가 제출되었습니다. 진짜 문제는 "클래스"메서드를 축소하면 클래스를 전달하고 호출 된 함수에서 해당 클래스의 새 인스턴스를 만들려면 최적화 된 코드가 제대로 작동하지 않는다는 것입니다. 아아. – seth

0

을 문제는 인터페이스의 프로토 타입에 정의하는 방법을 대 인터페이스 (A.say)에 정의 된 방법의 차이입니다 (A.prototype.say). 그것은 단지 프로토 타입에 방법에 대한 관심

Any class that implements an interface must implement all of the methods and properties defined on the interface's prototype.

주의 사항 : 폐쇄의 타입 시스템에서 @interface tag는 다음과 같은 보증을 제공합니다. 인터페이스 자체의 메소드는 상관하지 않습니다.

새 클래스, C이 있다고 가정하면 Sayer을 구현합니다. 닫히면 C.prototype.say을 정의해야합니다. 그러나 C.say을 건너 뛸 수 있습니다. 당신은 그것을 구현할 필요가 없습니다. 다음은 완벽하게 유효한 Sayer입니다. 이 유효한 Sayer을하기 때문에 makeSayer(C) 전화를

/** 
* @constructor 
* @implements {Sayer} 
*/ 
function C() {} 
C.prototype.say = function() { console.log('Am a C'); } 

, 우리는 안전합니다. 이제 makeSayer의 정의가 잘못된 이유가 분명합니다. cls.say이 정의되어 있다고 가정하지만 Closure는 그러한 보증을하지 않습니다. Closure가 문제를 찾아 내고 적절한 오류 메시지를 표시합니다.

그럼 어떻게해야합니까?

표준 객체 지향 접근법을 따르려면 공장 SayerFactory에 대해 하나, Say에 대해 하나씩 두 개의 인터페이스가 필요할 것입니다. 모든 메소드가 프로토 타입에 정의 된 메소드가되고 Closure가 모든 점검을 수행합니다.

그러나 생성자에 say 메서드를 사용하는 아이디어가 마음에 들면 오리 (duck) 입력을 사용하여 팩토리 메서드를 적용 해 볼 수 있습니다. 예 :

물론 여러 가지 방법을 정의해야 할 경우 오리 타이핑 방식이 잘 확장되지 않습니다. 형식 서명은 정의 된 각 메서드에 따라 커질 수 있습니다.

행운을 빈다.

관련 문제