Я вважаю, що використання комбінації інтерфейсів та базових класів могло б допомогти вам. Він буде виконувати поведінкові вимоги під час компіляції (rq_ пост "внизу" посилається на повідомлення вище, яке не є цим).
Інтерфейс встановлює API поведінки, який не відповідає базовому класу. Ви не зможете встановити методи базового класу для використання методів, визначених в інтерфейсі (тому що ви не зможете реалізувати цей інтерфейс у базовому класі, не визначаючи ці поведінки). Можливо, хтось може придумати безпечний трюк, щоб дозволити виклик методів інтерфейсу у батьків.
Ви повинні пам'ятати про розширення та впровадження у класі, який ви будете інстанціювати. Це задовольняє занепокоєння щодо визначення коду під час виконання програми. Ви навіть не зможете зателефонувати до методів, які могли б викликати, якщо ви не реалізували інтерфейс (наприклад, якщо ви намагаєтесь інстанціювати клас Animal). Я спробував, щоб інтерфейс розширив BaseAnimal внизу, але він приховав від Snake конструктор та поле "ім'я" BaseAnimal. Якби мені вдалося це зробити, використання модуля та експорту могло б запобігти випадковій прямій інстанції класу BaseAnimal.
Вставте це сюди, щоб перевірити, чи працює він для вас: http://www.typescriptlang.org/Playground/
// The behavioral interface also needs to extend base for substitutability
interface AbstractAnimal extends BaseAnimal {
// encapsulates animal behaviors that must be implemented
makeSound(input : string): string;
}
class BaseAnimal {
constructor(public name) { }
move(meters) {
alert(this.name + " moved " + meters + "m.");
}
}
// If concrete class doesn't extend both, it cannot use super methods.
class Snake extends BaseAnimal implements AbstractAnimal {
constructor(name) { super(name); }
makeSound(input : string): string {
var utterance = "sssss"+input;
alert(utterance);
return utterance;
}
move() {
alert("Slithering...");
super.move(5);
}
}
var longMover = new Snake("windy man");
longMover.makeSound("...am I nothing?");
longMover.move();
var fulture = new BaseAnimal("bob fossil");
// compile error on makeSound() because it is not defined.
// fulture.makeSound("you know, like a...")
fulture.move(1);
Я натрапив на відповідь FristvanCampen, як зазначено нижче. Він каже, що абстрактні класи є антидіаграмою, і припускає, що один екземпляр базових "абстрактних" класів використовує введений екземпляр класу, що реалізує. Це справедливо, але існують протилежні аргументи. Прочитайте самі:
https://typescript.codeplex.com/discussions/449920
Частина 2: У мене був інший випадок, коли я хотів отримати абстрактний клас, але мені було заборонено використовувати моє рішення вище, тому що визначені методи в "абстрактному класі" були необхідні для посилання на методи, визначені у відповідному інтерфейсі. Отже, я підбираю поради FristvanCampen, подібні. У мене неповний "абстрактний" клас із реалізацією методу. У мене є інтерфейс з нереалізованими методами; цей інтерфейс розширює "абстрактний" клас. Потім у мене є клас, який розширює перший і реалізує другий (він повинен поширюватись і тому, що супер конструктор недоступний в іншому випадку). Дивіться (не запускається) зразок нижче:
export class OntologyConceptFilter extends FilterWidget.FilterWidget<ConceptGraph.Node, ConceptGraph.Link> implements FilterWidget.IFilterWidget<ConceptGraph.Node, ConceptGraph.Link> {
subMenuTitle = "Ontologies Rendered"; // overload or overshadow?
constructor(
public conceptGraph: ConceptGraph.ConceptGraph,
graphView: PathToRoot.ConceptPathsToRoot,
implementation: FilterWidget.IFilterWidget<ConceptGraph.Node, ConceptGraph.Link>
){
super(graphView);
this.implementation = this;
}
}
і
export class FilterWidget<N extends GraphView.BaseNode, L extends GraphView.BaseLink<GraphView.BaseNode>> {
public implementation: IFilterWidget<N, L>
filterContainer: JQuery;
public subMenuTitle : string; // Given value in children
constructor(
public graphView: GraphView.GraphView<N, L>
){
}
doStuff(node: N){
this.implementation.generateStuff(thing);
}
}
export interface IFilterWidget<N extends GraphView.BaseNode, L extends GraphView.BaseLink<GraphView.BaseNode>> extends FilterWidget<N, L> {
generateStuff(node: N): string;
}