Простой ответ :
Если вам действительно не нужна ваша функция addNode (), чтобы принимать только AwareNode, вы можете просто изменить тип параметра на Node. Поскольку AwareNode расширяет Node, вы можете без проблем передавать AwareNode. Вы можете проверить правильность типа в теле функции:
subclass... {
override public function addNode (node:Node ) : Boolean {
if (node is AwareNode) return nodes.add(node);
return false;
}
}
Более длинный ответ :
Я согласен с @ 32bitkid, что вы получаете ошибку, потому что тип параметра, определенный для addNode () в вашем интерфейсе, отличается от типа в вашем подклассе.
Однако основная проблема заключается в том, что ActionScript, как правило, не допускает перегрузки функций (имея более одного метода с одинаковым именем, но с разными параметрами или возвращаемыми значениями), поскольку каждая функция обрабатывается как универсальный член класса - так же, как переменная. Вы можете вызвать такую функцию:
myClass.addNode (node);
но вы также можете назвать это так:
myClass["addNode"](node);
Каждый член хранится по имени - и вы всегда можете использовать это имя для доступа к нему. К сожалению, это означает, что вам разрешено использовать каждое имя функции в классе только один раз, независимо от того, сколько параметров какого типа оно принимает - ничего не обходится без цены: вы получаете гибкость в одном отношении, вы теряете некоторое удобство в другом.
Следовательно, вам разрешено переопределять методы только с одной и той же сигнатурой - это способ заставить вас придерживаться того, о чем вы решили, когда писали базовый класс. Хотя вы, очевидно, можете утверждать, что это плохая идея и что имеет больше смысла использовать перегрузку или разрешать разные подписи в подклассах, у способа, которым AS работает с функциями, есть некоторые преимущества, которые в конечном итоге помогут вам решить вашу проблему: можно использовать функцию проверки типа или даже передать ее в качестве параметра!
Учтите это:
class... {
protected function check (node:Node) : Boolean {
return node is Node;
}
public function addNode (node:Node) : Boolean {
if (check(node)) return nodes.add(node);
return false;
}
}
В этом примере вы можете переопределить проверку (узел: узел):
subclass... {
override protected function check (node:Node) : Boolean {
return node is AwareNode;
}
}
и добиться того же эффекта, который вы хотели, не нарушая контракт интерфейса - за исключением того, что в вашем примере компилятор выдаст ошибку, если вы передадите неверный тип, тогда как в этом случае ошибка будет видна только при время выполнения (false
возвращаемое значение).
Вы также можете сделать это еще более динамичным:
class... {
public function addNode (node:Node, check : Function ) : Boolean {
if (check(node)) return nodes.add(node);
return false;
}
}
Обратите внимание, что эта функция addNode принимает функцию в качестве параметра и что мы вызываем эту функцию вместо метода класса:
var f:Function = function (node:Node) : Boolean {
return node is AwareNode;
}
addNode (node, f);
Это позволит вам стать очень гибким в своей реализации - вы даже можете проверять достоверность анонимной функции, например, проверять содержимое узла. И вам даже не придется расширять свой класс, если только вы не собираетесь добавлять другие функции, кроме правильности ввода.
Наличие интерфейса также позволит вам создавать реализации, которые не наследуются от исходного базового класса - вы можете написать совершенно другую иерархию классов, для этого нужно только реализовать интерфейс, и весь ваш предыдущий код останется действительным.