JS++|虚拟方法

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

null

举个例子,让我们改变我们的主要观点。jspp代码使我们所有的动物都在一个数组中。从那里,我们将循环数组以渲染动物。打开主管道。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”语句。我们可以做一些更优雅的事情。

首先,开放动物。jspp并更改“render”方法以包含“virtual”修饰符:

external $;

module Animals
{
    class Animal
    {
        protected var $element;

        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;
        }
    }
}

拯救动物。jspp。这是我们唯一需要做的改变。

然而,仅仅将我们的方法虚拟化是不够的。在猫身上。jspp和狗。jspp,我们在他们的“渲染”方法中使用“覆盖”修饰符。“overwrite”修饰符指定编译时分辨率。我们需要运行时解析。我们所要做的就是换一只猫。jspp和狗。jspp使用“override”修饰符而不是“overwrite”修饰符。为了简洁起见,我将只显示对Cat的更改。jspp但是你需要改成狗。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了。所以只有 一句话 在循环内部:

import Animals;

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

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

编译代码并打开索引。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();
}

我们之所以能够如此显著地简化代码,是因为将方法标记为“虚拟”意味着潜在的运行时多态性。与“override”修饰符一起,编译器知道我们希望对“render”方法进行后期绑定,因此“late”绑定正好在需要时发生:当且仅当需要解析“render”方法时(在“foreach”循环内),才会在运行时解析“render”方法。

© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享