当前位置:  开发笔记 > 编程语言 > 正文

多态性与重写与重载

如何解决《多态性与重写与重载》经验,为你挑选了9个好方法。

就Java而言,当有人问:

什么是多态?

超载重载是一个可以接受的答案?

我认为还有更多的东西.

如果您有一个抽象基类定义了一个没有实现的方法,并且您在子类中定义了该方法,那还是会覆盖吗?

我认为超载肯定不是正确的答案.



1> Chris Cudmor..:

表达多态性的最清晰方式是通过抽象基类(或接口)

public abstract class Human{
   ...
   public abstract void goPee();
}

这个类是抽象的,因为这个goPee()方法不适用于人类.它只适用于男性和女性的子类.此外,人类是一个抽象的概念 - 你不能创造一个既不是男性也不是女性的人.它必须是一个或另一个.

所以我们通过使用抽象类来推迟实现.

public class Male extends Human{
...
    @Override
    public void goPee(){
        System.out.println("Stand Up");
    }
}

public class Female extends Human{
...
    @Override
    public void goPee(){
        System.out.println("Sit Down");
    }
}

现在我们可以告诉整个房间充满了人类去撒尿.

public static void main(String[] args){
    ArrayList group = new ArrayList();
    group.add(new Male());
    group.add(new Female());
    // ... add more...

    // tell the class to take a pee break
    for (Human person : group) person.goPee();
}

运行这将产生:

Stand Up
Sit Down
...


这个例子也很好地突出了使用分层系统来描述生物系统的难度.有些人,比如非常年轻,几乎在任何位置撒尿 - 而婴儿也不容易被告知goPee().有些人是双性人,其中"男性"或"女性"的生物标签变得相当不明确; 社会意义更加复杂.作为教学示例,它显示了建模假设如何产生负面结果,例如暗示失禁或双性人的某人(例如,OO编程的学生)实际上并不是人类.
@yuudachi.我在教课时想出了这个例子.规范的"银行账户"类并没有真正表达基类的"抽象性".另一个典型的例子(动物,制造噪音)太抽象了,无法理解.我正在寻找一个具有太明显的子类的单一基础.实际上,goPee()是我想出的唯一一个不是性别歧视或刻板印象的例子.(虽然在课堂上,我打印在"左边的大厅"而不是站起来或坐下.)
@AndrewDalke,+1关于生物复杂性的注释.此外,`goPee`不会将引力场作为输入.这种对全局状态的依赖使单元测试"CatheterizedIntersexAstronaut"变得困难,并表明子类化可能并不总是特征组合的最佳方法.
我能想到至少有少数人会反驳你的"你不能创造一个既不是男性也不能创造男性"的论点,尽管它仍然适用于你的代码...糟糕的抽象我想我说的是?;)

2> The Digital ..:

多态性是类实例的行为能力,就好像它是其继承树中另一个类的实例,通常是其祖先类之一.例如,在Java中,所有类都继承自Object.因此,您可以创建Object类型的变量,并为其分配任何类的实例.

一个覆盖是一种函数,它发生在一个继承自另一个类的类中.覆盖函数"替换"从基类继承的函数,但这样做的方式是,即使其类的实例假装通过多态而成为不同的类型,也会调用它.参考前面的示例,您可以定义自己的类并覆盖toString()函数.因为此函数是从Object继承的,所以如果将此类的实例复制到Object类型变量中,它仍然可用.通常,如果在假装是Object时调用类上的toString(),实际触发的toString版本就是在Object本身定义的版本.但是,因为函数是一个覆盖,所以即使在类实例中,也会使用类中toString()的定义.

重载是定义具有相同名称但具有不同参数的多个方法的操作.它与重写或多态无关.


不正确."Ad hoc多态性"是你在**重载**部分中描述的,*是*多态的情况.
这是旧的,但是Polymorphism并不意味着另一个类必须在继承树中.如果您认为接口是继承树的一部分,那么它在Java中完成,而在Go中则不是,其中接口是隐式实现的.
实际上,根本不需要多态类.
我是新手,如果我错了,请纠正我,但我不会说重载与多态无关.至少在Java中,多态性是在根据调用者的类型选择实现时,而重载是在根据参数的类型选择实现时,不是吗?看到两者之间的相似性有助于我理解它.

3> Mark A. Nico..:

这是伪C#/ Java中的多态性示例:

class Animal
{
    abstract string MakeNoise ();
}

class Cat : Animal {
    string MakeNoise () {
        return "Meow";
    }
}

class Dog : Animal {
    string MakeNoise () {
        return "Bark";
    }
}

Main () {
   Animal animal = Zoo.GetAnimal ();
   Console.WriteLine (animal.MakeNoise ());
}

Main函数不知道动物的类型,并且取决于MakeNoise()方法的特定实现的行为.

编辑:看起来Brian打败了我.有趣的是我们使用相同的例子.但上面的代码应该有助于澄清这些概念.



4> 小智..:

多态性是指不止一种形式,同一对象根据需要执行不同的操作.

多态性可以通过两种方式实现,即那些方式

    方法覆盖

    方法重载

方法重载意味着使用相同的方法名称在同一个类中编写两个或多个方法,但传递参数不同.

方法重写意味着我们在不同的类中使用方法名称,这意味着在子类中使用父类方法.

在Java中实现多态,超类引用变量可以保存子类对象.

要实现多态性,每个开发人员必须在项目中使用相同的方法名称.


+1回答很好.接受的答案只解释了一种多态性.这个答案是完整的.

5> Patrick McEl..:

覆盖和重载都用于实现多态性.

您可以在一个或多个子类中重写的类中拥有一个方法.该方法根据用于实例化对象的类来执行不同的操作.

    abstract class Beverage {
       boolean isAcceptableTemperature();
    }

    class Coffee extends Beverage {
       boolean isAcceptableTemperature() { 
           return temperature > 70;
       }
    }

    class Wine extends Beverage {
       boolean isAcceptableTemperature() { 
           return temperature < 10;
       }
    }

您还可以使用两个或多个参数集重载的方法 .该方法根据传递的参数类型执行不同的操作.

    class Server {
        public void pour (Coffee liquid) {
            new Cup().fillToTopWith(liquid);
        }

        public void pour (Wine liquid) {
            new WineGlass().fillHalfwayWith(liquid);
        }

        public void pour (Lemonade liquid, boolean ice) {
            Glass glass = new Glass();
            if (ice) {
                glass.fillToTopWith(new Ice());
            }
            glass.fillToTopWith(liquid);
        }
    }


正如我在此回答的那样,我不同意 - 这两个特征不是正交的,而是密切相关的.多态性!=继承.你有我的投票权.
换句话说,键入多态与ad-hoc多态.我正在推荐这个答案,即使它没有尽可能完整,因为它正确地指出重载和覆盖都与多态性有关.说OOP语言中的多态只能通过类继承实现是完全错误的 - 我们应该记住除了Java和C++之外还有一些其他的OOP语言,其中可以使用多重调度,ad hoc多态,参数多态等概念. .
@rsenna这可能是不完整的,但它比其他恕我直言更好地回答了这个问题.另外,非常好的是你提到了ad-hoc和参数多态.

6> Alex B..:

你是正确的,重载不是答案.

两者都不是最重要的.覆盖是获得多态性的手段.多态性是对象根据其类型改变行为的能力.当展示多态性的对象的调用者不知道对象是什么特定类型时,这是最好的证明.


它不应该是对象的行为改变,而是他的实现.相同的行为,不同的实现,这是多态性.

7> Peter Meyer..:

特别是说重载或覆盖不能全面展示.多态性只是一个对象根据其类型专门化其行为的能力.

我不同意这里的一些答案,因为在具有相同名称的方法可以表现不同的情况下,重载是多态(参数多态)的一种形式,给出不同的参数类型.一个很好的例子是运算符重载.您可以定义"+"以接受不同类型的参数 - 比如字符串或int - 并且基于这些类型,"+"将表现不同.

多态性还包括继承和重写方法,尽管它们可以是基本类型中的抽象或虚拟.就基于继承的多态性而言,Java仅支持单类继承,将其多态行为限制为单个基类型链的行为.Java确实支持多接口的实现,这是多态行为的另一种形式.


要明确的是,我认为应该说明不同的形式 - 我甚至没有充分地做过 - 因为这里有一些答案是绝对的.我恭敬地不同意在"程序员上下文......'多态性'总是意味着'基于继承的多态''
我认为重载最好归类为Ad-hoc_polymorphism http://en.wikipedia.org/wiki/Parametric_polymorphism#Ad-hoc_polymorphism_with_early_binding

8> 小智..:

多态只是意味着"多种形式".

它没有要求继承来实现...因为接口实现(根本不是继承)满足多态需求.可以说,接口实现为继承提供了"更好"的多态需求.

例如,你会创建一个超类来描述所有可以飞行的东西吗?我不应该想.您最好能够创建一个描述航班的界面并将其留在那里.

因此,由于接口描述了行为,并且方法名称描述了行为(对程序员而言),因此将方法重载视为较小形式的多态性并不是一件容易的事.


绝对是最好的答案。多态可以应用于所有语言结构,无论是名词(类)还是动词(方法)。

9> Brian G..:

经典的例子,狗和猫是动物,动物有makeNoise的方法.我可以遍历一系列动物,在它们上面调用makeNoise,并期望它们会在那里进行相应的实现.

调用代码不必知道它们是什么特定的动物.

这就是我认为的多态性.

推荐阅读
yzh148448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有