開発中の API に問題があります。それぞれが同じインターフェイスを実装し、静的メソッドを持つクラスの配列が必要です。クラスの配列を循環し、静的メソッドの 1 つの戻り値に基づいて 1 つを選択する別のクラスがありますが、コンパイラは静的メソッドを削除しており、javascript は静的メソッドを呼び出そうとすると TypeError に遭遇します。 . いくつかのフォーラムを検索してみましたが、役立つものが見つかりません。このエラーは、単純ではなく高度なコンパイル モードでのみ発生し、デバッグ モードでの高度なコンパイルでも発生します。
これは、私が関数を呼び出している複雑な方法のために、関数を使用していることをコンパイラが認識していないためだと考えています。
エラーの原因となる、私がやろうとしていることのやや単純化された例をまとめました。
コードについては以下を参照してください。
Racer
インターフェイスは、 と の 2 つのクラスによって実装されるRunner
インターフェイスですJogger
。インターフェイスには、レーサーが移動できる方法の配列を返す getModesOfTransportation と呼ばれる 1 つの静的メソッドと、同じことを行う getTransportationModes と呼ばれるインスタンス メソッドがあります。このファイルは、キーワードracing.RacerClass
で呼び出されたときにレーサー オブジェクトを返す関数である型を (私が思うに) 作成するカスタム型 も定義します。https://developers.google.com/closure/compiler/docs/js-for-compiler#typesnew
に基づいてこれを作成しました。型にも静的メソッドがあることを定義する必要があると思いますが、方法がわかりません。このカスタム タイプがエラーの原因でしょうか?
racer.js:
goog.provide('racing.Racer');
/** @typedef function(new:racing.Racer)*/
racing.RacerClass={};// My custom typedef
/**
* Interface for racers.
* @interface
*/
racing.Racer=function(){};
/**
* Gets the ways this racer can move.
* @return {Array.<string>} The ways this racer can move.
*/
racing.Racer.getModesOfTransportation=function(){}
/**
* Gets the ways this racer can move.
* @return {Array.<string>} The ways this racer can move.
*/
racing.Racer.prototype.getTransportationModes=function(){}
このHelper
クラスには、Racer コンストラクターのリストが格納されます。このregisterRacer
関数は、a のコンストラクターを受け取り、Racer
それをリストに追加します。渡されたコンストラクター関数には、静的getModesOfTransportation
関数も含まれます。このgetRacers
関数は、登録されているレーサーのリストを返します。
helper.js:
goog.provide('racing.Helper');
/**
* A collection of functions to help with finding racers.
*/
racing.Helper={};
/**
* An array of racers.
* @type {Array.<racing.RacerClass>}
* @private
*/
racing.Helper.racers_=[]
/**
* Adds the given racer to the list.
* @param {racing.RacerClass} racer A racer to add to the list of racers.
*/
racing.Helper.registerRacer=
function(racer){
racing.Helper.racers_.push(racer);
}
/**
* Gets an array of registered racers.
* @return Array.<racing.RacerClass> A list of all registered racers.
*/
racing.Helper.getRacers=
function(){
return racing.Helper.racers_;
}
このJogger
クラスはRacer
インターフェイスを実装し、2 つの関数の戻り値は['jog']
次のとおりです。ファイルの最後で、それ自体をヘルパーに登録します。
ジョガー.js:
goog.provide('racing.Jogger');
goog.require('racing.Racer');
goog.require('racing.Helper');
/**
* This racer can jog.
* @constructor
*/
racing.Jogger=function(){
console.log('Jogger is going');
};
/**
* Gets the ways this racer can move.
* @static
* @return {Array.<string>} The ways this racer can move.
*/
racing.Jogger.getModesOfTransportation=
function(){
return ['jog'];//I can jog
}
/**
* Gets the ways this racer can move.
* @return {Array.<string>} The ways this racer can move.
*/
racing.Jogger.prototype.getTransportationModes=
function(){
return ['jog'];//I can jog
}
//Register this racer
racing.Helper.registerRacer(racing.Jogger);
このRunner
クラスもRacer
インターフェイスを実装していますが、2 つの関数の戻り値は['run']
、ファイルの最後で自身をヘルパーに登録します。
ランナー.js:
goog.provide('racing.Runner');
goog.require('racing.Racer');
goog.require('racing.Helper');
/**
* This racer can run.
* @constructor
*/
racing.Runner=
function(){
console.log('Runner is going');
};
/**
* Gets the ways this racer can move.
* @static
* @return {Array.<string>} The ways this racer can move.
*/
racing.Runner.getModesOfTransportation=
function(){
return ['run'];//I can run
}
/**
* Gets the ways this racer can move.
* @return {Array.<string>} The ways this racer can move.
*/
racing.Runner.prototype.getTransportationModes=
function(){
return ['run'];//I can run
}
//Register this racer
racing.Helper.registerRacer(racing.Runner);
このOrganizer
クラスには、保護された関数を呼び出すことによって実行できるstartRace
のインスタンスを取得および格納するというパブリック関数があります。関数はレーサーのリストを巡回し、実行できるレーサーを見つけようとしますが、コードがコンパイルされると、それは未定義であると言って失敗します。Racer
getRunner
getRunner
racerClass.getModesOfTransportation()
getModesOfTransportation
オーガナイザー.js:
goog.provide('racing.Organizer');
goog.require('racing.Helper');
goog.require('goog.array');
/**
* Class that helps with starting a race.
* @constructor
*/
racing.Organizer=function(){}
/**
* A racer that can run.
* @protected
* @returns {racing.Racer}
*/
racing.Organizer.prototype.runner=null;
/**
* Get a racer that can run.
* @protected
* @returns {racing.Racer}
*/
racing.Organizer.prototype.getRunner=
function(){
//Cycle through the racers until we find one that can run.
goog.array.findIndex(racing.Helper.getRacers(),
function(racerClass){
if(goog.array.contains(racerClass.getModesOfTransportation(),'run')){
this.runner=new racerClass();
return true;
}
else return false;
},this
);
}
/**
* Starts a race.
*/
racing.Organizer.prototype.startRace=
function(){
this.runner=this.getRunner();
}
最終的なファイルには、コンパイラのすべてのクラスが含まれています。
API.js:
//Include the racers
goog.require('racing.Runner');
goog.require('racing.Jogger');
//Include the organizer and export its properties
goog.require('racing.Organizer')
goog.exportSymbol('racing.Organizer', racing.Organizer);
goog.exportProperty(racing.Organizer.prototype, 'startRace', racing.Organizer.prototype.startRace);
new racing.Organizer().startRace();
コンパイルされたコードをデバッグ モードで実行すると、次のエラーが発生し、コンパイルされたコードを見ると、getModesOfTransportation
関数が存在しなくなります。
Uncaught TypeError: Object function () {
console.log("Runner is going")
} has no method '$getModesOfTransportation$'
$$racing$Organizer$$$$$startRace$$
(anonymous function)
クラスを静的関数のみのクラスとコンストラクターのみのクラスに分割することなく、これを機能させたいと考えています。コードが混乱するためです。私はこれを理解しようとしましたが、できません。
アイデア/提案をお寄せいただきありがとうございます。