Страницы

Поиск по вопросам

вторник, 25 июня 2019 г.

Имитация множественного наследования

Есть класс и функция-конструктор. Делается попытка реализовать класс, являющийся чем-то типа потомка обоих. Точнее, методы из прототипа функции-конструктора копируются в прототип класса-потомка, унаследованный от класса.
Да, я понимаю, что это не полноценное наследование, но для решения задачи этого хватает.
Проблема в другом. Как заставить тайпскрипт воспринимать копируемые методы?
class First { someMethod() { console.log('someMethod from First'); } }
function Second() { console.log('Second'); }
Second.prototype.doSmth = function () { console.log('doSmth from Second'); }
interface IBoth { someMethod() doSmth() }
class Both extends First /* implements IBoth */ { constructor() { console.log('constructor of Both'); super(); Second.call(this); } }
for (let key in Second.prototype) { Both.prototype[key] = Second.prototype[key]; }
На самом деле, надо обеспечить видимость методов ещё на уровень дальше
class Final extends Both { doIt() { this.someMethod(); //this.doSmth(); // Надо заставить видеть метод тут (this as any as IBoth).doSmth(); // Компилируется, но это ужас } }
если при этом методы не будут видны из самого Both, то это годится.
Вот что я уже пробовал:
При попытке написать
class Both extends First implements IBoth {
возникает ошибка, что я не реализую методы интерфейса. При переименовании Both в _Both и использовании
var Both = _Both as typeof _Both;
всё остаётся как было, что логично, поскольку тут никак не используется First При переименовании Both в _Both и использовании
var Both = _Both as typeof IBoth;
говорит, что не может найти имя IBoth
Пробовал ещё несколько вариантов, но они совсем бредовые. Что ещё можно сделать?

Попробовать можно тут: http://www.typescriptlang.org/Playground Полный код для проверки
Запустить (код из правой панели) после добавления строки:
(new Final).doIt();
Вывод при запуске при раскомментированной строке this.doSmth();
constructor of Both Second someMethod from First doSmth from Second doSmth from Second

PS: Этот вопрос на английском.


Ответ

Интерфейс вообще не нужен, нужно просто объявить прототипное поле с нужным типом:
doSmth: () => void
Она видима как свойство, а не как метод, но это непринципиально.
Полный код:
class First { someMethod() { console.log('someMethod from First'); } }
function Second() { console.log('Second'); }
Second.prototype.doSmth = function () { console.log('doSmth from Second'); }
class Both extends First { constructor() { console.log('constructor of Both'); super(); Second.call(this); }
doSmth: () => void }
for (let key in Second.prototype) { Both.prototype[key] = Second.prototype[key]; }
class Final extends Both { doIt() { this.someMethod(); this.doSmth(); //Both.prototype.doSmth(); // ok //Final.prototype.doSmth(); // ok } }
PS: Надо было гуглить не всяческие варианты с наследованием, а typescript class prototype variable - сразу нашёл подходящий вариант.

Комментариев нет:

Отправить комментарий