JS++ |事件处理程序
我们已经将我们的“动物”类抽象化了。我们已经声明了一个抽象的“talk”方法并在“Animal”的所有子类中实现了这个方法。然而,我们的动物还不会说话。我们需要一种方法来让动物在事件发生时有所作为。在这种情况下,我们想要的“做某事”是让动物说话,而需要发生的“事件”将是用户鼠标点击。我们可以使用事件处理程序来做到这一点。
jQuery 提供事件处理,但我们将以面向对象的方式定义事件处理程序。使用抽象类,您不需要将事件挂钩到每个单独的类。相反,您可以将事件附加到抽象类并将其应用于所有子类。
修改 Animal.jspp 如下:
external $;
module Animals
{
abstract class Animal
{
protected var $element;
private static unsigned int count = 0;
protected Animal(string iconClassName) {
string elementHTML = makeElementHTML(iconClassName);
$element = $(elementHTML);
attachEvents();
Animal.count++;
}
public static unsigned int getCount() {
return Animal.count;
}
public virtual void render() {
$("#content").append($element);
}
public abstract void talk();
private void attachEvents() {
$element.click(talk);
}
private string makeElementHTML(string iconClassName) {
string result = '';
result += '';
result += "";
return result;
}
}
}
这就是您必须添加的全部内容。编译项目并尝试单击动物。当您单击动物(犀牛除外)时,您应该会看到弹出的消息框并看到它发出的噪音:
让我们分解代码。我们声明了一个私有的“attachEvents”方法。我们将其设为“私有”,因为只有“动物”类需要它。在“Animal”构造函数中,我们调用“attachEvents”方法。在这一点上这应该很简单。这是带有新材料的代码;在 'attachEvents' 方法中,我们有这样的语句:
$element.click(talk);
您会记得,通过继承,“Animal”的每个子类也将具有“$element”作为数据。该元素对于类的每个实例都是唯一的。 '$element' 字段代表一个 jQuery 对象,由其 $ 前缀表示。然后,我们使用 jQuery 将“事件侦听器”附加到每个实例唯一的“$element”。
因此,当我们实例化“Cat”、“Dog”、“Panda”和“Rhino”时,我们将为每个执行相应的构造函数,首先执行 super() 调用以从“Animal”类继承。 'Animal' 反过来为类实例创建一个唯一的 '$element' 并将 'click' 事件侦听器附加到元素。因此,即使只修改了抽象基类(“Animal”),我们的每个实例都附加了一个事件。
此外,我们传递了 'talk' 方法作为对 'click' 的引用。 'click' 和 'talk' 都是函数。但是,只有 'click' 使用函数调用语法(带括号)。我们没有在“talk”之后添加括号。原因是我们不希望“谈话”立即执行。我们只希望在“click”事件发生时执行“talk”。
事件侦听器将一直等到事件发生。在这种情况下,我们附加了一个“单击”事件,因此当用户用鼠标单击元素时将触发该事件。最后,我们必须指定单击元素时执行哪个方法:
$element.click(talk);
如您所见,我们将 'talk' 方法作为“事件处理程序”传递。事件处理程序是在事件被触发时执行的方法。换句话说,我们希望在单击元素时执行 'talk' 方法。
然而,“谈话”是抽象的。 JS++ 认识到我们有一个抽象类,并且我们正在传递一个抽象方法。由于抽象方法无法执行,JS++会解析正确的方法来执行。在这种情况下,它将解析为 'talk' 的相应子类实现。