JS++ 虚拟方法

JS++ 虚拟方法

正如我们在上一节中提到的,如果我们想要运行时的多态性,使用铸模会导致代码不干净。

举例来说,让我们改变main.jspp的代码,使我们所有的动物都在一个数组内。在这里,我们将在数组上进行循环,以渲染动物。打开main.jspp,把代码改成。

import Animals;

Animal[] animals = [
    new Cat("Kitty"),
    new Cat("Kat"),
    new Dog("Fido"),
    new Panda(),
    new Rhino()
];

foreach(Animal animal in animals) {
    if (animal instanceof Cat) {
        ((Cat) animal).render();
    }
    else if (animal instanceof Dog) {
        ((Dog) animal).render();
    }
    else {
        animal.render();
    }
}

现在我们的代码甚至不如我们原来的代码优雅,我们只是实例化了动物,指定了最具体的类型,然后调用render()。

然而,这段代码可以被大量简化,直到它变得优雅。事实上,我们可以将 “foreach “循环减少到一条语句。答案是:虚拟方法。

虚拟方法实现了 “晚期绑定”。换句话说,要调用的具体方法是在运行时而不是编译时解决的。我们不需要所有的 “instanceof “检查、所有的转换和所有的 “if “语句,正如我们在上面的代码中看到的那样。我们可以实现更优雅的东西。

首先,打开Animal.jspp,改变’render’方法,使其包括’virtual’修饰符。

external ;

module Animals
{
    class Animal
    {
        protected varelement;

        protected Animal(string iconClassName) {
            string elementHTML = makeElementHTML(iconClassName);
            element =(elementHTML);
        }

        public virtual void render() {
            ("#content").append(element);
        }

        private string makeElementHTML(string iconClassName) {
            string result = '<div class="animal">';
            result += '<i class="icofont ' + iconClassName + '"></i>';
            result += "</div>";
            return result;
        }
    }
}

保存Animal.jspp,这就是我们需要做的唯一改动。

然而,仅仅使我们的方法成为虚拟的还不够。在Cat.jspp和Dog.jspp中,我们在它们的’render’方法上使用’overwrite’修改器。覆盖 “修饰符指定了编译时的分辨率。我们想要的是运行时分辨率。我们要做的就是改变Cat.jspp和Dog.jspp,使用 “覆盖 “修饰符,而不是 “覆盖 “修饰符。为了简洁起见,我将只展示对Cat.jspp的修改,但你也需要对Dog.jspp进行修改。

external ;

module Animals
{
    class Cat : Animal
    {
        string _name;

        Cat(string name) {
            super("icofont-animal-cat");
            _name = name;
        }

        override void render() {element.attr("title", _name);
            super.render();
        }
    }
}

就是这样。我们所要做的就是改变修改器。现在我们终于可以编辑main.jspp了,这样循环内就只有一条语句了。

import Animals;

Animal[] animals = [
    new Cat("Kitty"),
    new Cat("Kat"),
    new Dog("Fido"),
    new Panda(),
    new Rhino()
];

foreach(Animal animal in animals) {
    animal.render();
}

编译你的代码并打开index.html。一切都应该工作。现在,我们已经能够大规模地简化我们的代码,并仍然得到预期的行为。具体来说,我们将 “foreach “循环的代码从以下几个方面减少了。

foreach(Animal animal in animals) {
    if (animal instanceof Cat) {
        ((Cat) animal).render();
    }
    else if (animal instanceof Dog) {
        ((Dog) animal).render();
    }
    else {
        animal.render();
    }
}

对这一点。

foreach(Animal animal in animals) {
    animal.render();
}

我们之所以能够如此大幅度地简化代码,是因为将一个方法标记为 “虚拟 “意味着潜在的运行时多态性。与 “覆盖 “修饰符一起,编译器知道我们想在 “渲染 “方法上进行后期绑定,所以 “后期 “绑定正好发生在需要的时候:”渲染 “方法将在运行时被解析,如果并且只有在它需要被解析的时候(在 “foreach “循环中)。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程