Компилятор Google Closure: класс в качестве аргумента функции - PullRequest
0 голосов
/ 27 января 2020

Я не могу понять, как отправлять ссылки на классы в качестве аргументов функции, чтобы компилятор Google Closure компилировал его прямо в расширенном режиме. В приведенном ниже примере я отправляю ссылку на класс в функцию Test1.doSomething, которая вызывает функцию класса c для класса. Я установил @param в Function, потому что я думаю, что это все еще функция, хотя я использую классы стиля ES6. Есть ли какое-то другое ключевое слово, которое я должен использовать?

Приведенный ниже код прекрасно работает без компиляции, а также отлично работает, если я go old school и заменю «class Test2» на «function Test2 ()». Я также пытался изменить @param на function (), function (new: Test2), function (this: Test2), typeof Test2, et c, но безуспешно.

class Test1
{
    /**
     * @param {!Function} typeRef   
     */    
    doSomething(typeRef)
    {
        typeRef.doSomething();
    }
}

class Test2
{
}

Test2.doSomething = function()
{
    alert(1);
}

var t1 = new Test1();
window["t1"] = t1;
t1.doSomething(Test2);

Я компилирую следующим образом:

--debug --formatting=PRETTY_PRINT --language_in ECMASCRIPT6_STRICT --language_out ECMASCRIPT6_STRICT --compilation_level ADVANCED_OPTIMIZATIONS --js Test.js --js_output_file Script.js

Результат с "class Test2"

'use strict';
class $Test1$$ {
}
window.t1 = new $Test1$$;

Результат с "function Test2 ()"

'use strict';
class $Test1$$ {
  $doSomething$($typeRef$$) {
    $typeRef$$.$doSomething$();
  }
}
function $Test2$$() {
}
$Test2$$.$doSomething$ = function $$Test2$$$$doSomething$$() {
  alert(1);
};
var $t1$$ = new $Test1$$;
window.t1 = $t1$$;
$t1$$.$doSomething$($Test2$$);

EDIT ON 29 ЯНВ: Добавлен более полный пример того, что я пытаюсь сделать:

class Car
{
    constructor()
    {
        this.make = "Ford";
        console.log("Car created.");
    }
}
Car.create = function(registry)
{
    let obj = new Car();
    registry.add(obj);
    return obj;
}

class Motorcycle
{
    constructor()
    {
        this.make = "BMW";
        console.log("Motorcycle created.");
    }
}
Motorcycle.create = function(registry)
{
    let obj = new Motorcycle();
    registry.add(obj);
    return obj;
}

class Registry
{
    constructor()
    {
        this.vehicles = [];
    }
    add(vehicle)
    {
        this.vehicles.push(vehicle);
    }
    makeVehicle(typeRef)
    {
        typeRef.create(this);
    }

}

function init()
{
    var registry = new Registry();

    registry.makeVehicle(Car);
    registry.makeVehicle(Motorcycle);
    registry.makeVehicle(Motorcycle);
    registry.makeVehicle(Car);
    registry.makeVehicle(Car);
}

1 Ответ

0 голосов
/ 28 января 2020

Чтобы перейти в класс, вы можете использовать тип {typeof namespace}:

@param {typeof Test2} TypeRef   

Как в вашем коде:

class Test1
{
    /**
     * @param {typeof Test2} TypeRef   
     */    
    doSomething(TypeRef)
    {
        (new TypeRef()).doSomething();
    }
}

class Test2
{
  doSomething ()
  {
    alert(1);
  }
}

var t1 = new Test1();
window["t1"] = t1;
t1.doSomething(Test2);

Демо (не забудьте нажать Compile)

При использовании @param (без typeof) вы передаете экземпляр этого типа *. Это гораздо чаще, чем передача самого класса

*: извините, если это не актуально, но я заметил несколько проблем в исходном коде и хотел показать вам, как их исправить, даже если они не актуальны;

Чтобы создать версию с типом экземпляра, мне пришлось изменить 3 вещи:

1) Назначение Test2.doSomething должно присваивать Test2.prototype;

Test2.prototype.doSomething = function()
{
    alert(1);
}

Или используя формат класса ES6:

Test2 
{
    doSomething() 
    {
         alert(1);
    }
}

2) И чтобы разрешить предупреждение Test1.doSomething, аннотация @param должна была стать Type2, так как функция не объявляет метод Function.doSomething .

/**
 * @param {!Type2} typeRef   
 */

3) Последняя строка передает сам класс, а не экземпляр класса, поэтому вы должны использовать оператор new для отправки экземпляра этого класса.

t1.doSomething(new Test2());

Приветствия.

...