Расширенное наследование JavaScript в TypeScript - PullRequest
0 голосов
/ 01 октября 2018

Расширенное наследование JavaScript в TypeScript

Одним из замечательных аспектов JavaScript является количество различных способов, которыми объекты могут наследовать инкапсуляцию от других.Тем не менее, TypeScript накладывает жесткие ограничения на возможности написания модуля с этой точки зрения.

В JavaScript у вас есть возможность достичь множественного наследования - скорее, функции Mixin - с помощью Перехват конструктора , который является чрезвычайно мощной функцией языка:

var Base = function Base() {

    function f() {
        console.log('datum: %s', this.datum);
    }

    function method() {
        this.a();
        this.b();
        this.c();
    }

    // export precepts
    this.datum = true;
    this.f = f;
    this.method = method;

    return this;
};

var A = function A() {

    function a() {
        this.f();
    }

    // export precepts
    this.a = a;

    return this;
};
var B = function B() {

    function b() {
        this.f();
    }

    // export precepts
    this.b = b;

    return this;
};
var C = function C() {

    function c() {
        this.f();
    }

    // export precepts
    this.c = c;

    return this;
};

var Klass = function Klass() {
    var config = { };

    function init() {
        this.method();
    }

    // export precepts
    Base.call(this);
    A.call(this);
    B.call(this);
    C.call(this);
    this.config = config;
    this.init = init;

    return this;
};

var klass = new Klass();
klass.init();
// > datum: true
// > datum: true
// > datum: true

Это позволяет разработчику разбивать свой код на отдельные модули, которым нужно следовать только шаблону или соглашению, чтобы расширить другоймодуль, сохраняя принцип единой ответственности и принцип открытого и закрытого использования SOLID нетронутым.

Анализ

Приведенный выше код должен регистрировать строку datum: true 3 раза.Это связано с тем, что Klass украшает (или смешивает) класс Base, так что классы A-C не выдают ошибку времени выполнения при вызове this.f.CallStack процесса выглядит примерно так:

  • [Класс] init
  • [Базовый] метод
  • [A] a
  • [База] f
  • [Консоль] log
  • [B] b
  • [База] f
  • [Консоль] log
  • [C] c
  • [Base] f
  • [Console] log

Примечания

CallStack довольно произвольный и тривиальный.Кроме того, этот код можно рассматривать как несолидный, но просто предположим, что мы используем шаблон шаблонного метода, если он помогает обойти грубость примера.

Кроме того, несомненно, будет душапередать и сказать кое-что о том, что все, что мы знаем о примере выше, нарушает TypeScript.Имейте в виду, что «TypeScript - это расширенный набор JavaScript» - это просто, прямо и явно неправильно - я даже не буду спорить, почему, вы уже должны это знать, если используете TypeScript.

Вопрос:

Учитывая приведенный выше код, как можно достичь такой функциональности, используя правильный синтаксис TypeScript?Я также открыт для использования шаблонов проектирования, если это необходимо, хотя это все еще не идеально.

1 Ответ

0 голосов
/ 02 октября 2018

Mixins даст вам большую часть того, что вы хотите.Ваш пример будет:

class Base { 
    datum = true;
    // We can't make these methods abstract because TypeScript currently
    // doesn't support tracking whether mixins implement abstract methods. 
    a() {
        throw new Error("not implemented");
    }
    b() {
        throw new Error("not implemented");
    }
    c() {
        throw new Error("not implemented");
    }
    f() {
        console.log('datum: %s', this.datum);
    }
    method() { 
        this.a();
        this.b();
        this.c();
    }
}

function mixA<Orig extends {new(...args: any[]): Base}>(base: Orig) { 
    return class extends base {
        a() {
            this.f();
        }
    };
}
function mixB<Orig extends {new(...args: any[]): Base}>(base: Orig) { 
    return class extends base {
        b() {
            this.f();
        }
    };
}
function mixC<Orig extends {new(...args: any[]): Base}>(base: Orig) { 
    return class extends base {
        c() {
            this.f();
        }
    };
}

class Klass extends mixA(mixB(mixC(Base))) { 
    config = {};
    init() { 
        this.method();
    }
}

var klass = new Klass();
klass.init();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...