Java 多态 vs 覆盖 vs 重载

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/154577/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 09:01:25  来源:igfitidea点击:

Polymorphism vs Overriding vs Overloading

javaooppolymorphismoverloadingoverriding

提问by Brian G

In terms of Java, when someone asks:

在Java方面,当有人问:

what is polymorphism?

什么是多态?

Would overloadingor overridingbe an acceptable answer?

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

I think there is a bit more to it than that.

我认为还有更多的东西。

IF you had a abstract base class that defined a method with no implementation, and you defined that method in the sub class, is that still overridding?

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

I think overloadingis not the right answer for sure.

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

采纳答案by Chris Cudmore

The clearest way to express polymorphism is via an abstract base class (or interface)

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

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

This class is abstract because the goPee()method is not definable for Humans. It is only definable for the subclasses Male and Female. Also, Human is an abstract concept — You cannot create a human that is neither Male nor Female. It's got to be one or the other.

这个类是抽象的,因为该goPee()方法不可为人类定义。它只能为子类男性和女性定义。此外,人类是一个抽象的概念——你不能创造一个既不是男性也不是女性的人。它必须是其中之一。

So we defer the implementation by using the abstract class.

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

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

and

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

Now we can tell an entire room full of Humans to go pee.

现在我们可以告诉整个房间里挤满了人类去小便。

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

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

Running this would yield:

运行这将产生:

Stand Up
Sit Down
...

回答by Clyde

The term overloading refers to having multiple versions of something with the same name, usually methods with different parameter lists

术语重载是指具有相同名称的多个版本,通常是具有不同参数列表的方法

public int DoSomething(int objectId) { ... }
public int DoSomething(string objectName) { ... }

So these functions might do the same thing but you have the option to call it with an ID, or a name. Has nothing to do with inheritance, abstract classes, etc.

因此,这些函数可能会做同样的事情,但您可以选择使用 ID 或名称来调用它。与继承、抽象类等无关。

Overriding usually refers to polymorphism, as you described in your question

正如您在问题中所描述的,覆盖通常是指多态性

回答by Alex B

You are correct that overloading is not the answer.

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

Neither is overriding. Overriding is the means by which you get polymorphism. Polymorphism is the ability for an object to vary behavior based on its type. This is best demonstrated when the caller of an object that exhibits polymorphism is unaware of what specific type the object is.

两者都不是压倒性的。覆盖是获得多态性的手段。多态性是对象根据其类型改变行为的能力。当表现出多态性的对象的调用者不知道该对象是什么特定类型时,这是最好的证明。

回答by Matt

overloading is when you define 2 methods with the same name but different parameters

重载是指定义 2 个名称相同但参数不同的方法

overriding is where you change the behavior of the base class via a function with the same name in a subclass.

覆盖是您通过子类中具有相同名称的函数更改基类行为的地方。

So Polymorphism is related to overriding but not really overloading.

所以多态与覆盖有关,但与重载无关。

However if someone gave me a simple answer of "overriding" for the question "What is polymorphism?" I would ask for further explanation.

但是,如果有人就“什么是多态性?”这个问题给了我一个简单的“覆盖”答案。我会要求进一步的解释。

回答by mxg

Polymorphism is the ability for an object to appear in multiple forms. This involves using inheritance and virtual functions to build a family of objects which can be interchanged. The base class contains the prototypes of the virtual functions, possibly unimplemented or with default implementations as the application dictates, and the various derived classes each implements them differently to affect different behaviors.

多态性是一个对象以多种形式出现的能力。这涉及使用继承和虚函数来构建可以互换的对象系列。基类包含虚函数的原型,可能未实现或具有应用程序指示的默认实现,并且各种派生类各自以不同的方式实现它们以影响不同的行为。

回答by Brian G

The classic example, Dogs and cats are animals, animals have the method makeNoise. I can iterate through an array of animals calling makeNoise on them and expect that they would do there respective implementation.

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

The calling code does not have to know what specific animal they are.

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

Thats what I think of as polymorphism.

这就是我认为的多态性。

回答by Mark A. Nicolosi

Here's an example of polymorphism in pseudo-C#/Java:

下面是伪 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 ());
}

The Main function doesn't know the type of the animal and depends on a particular implementation's behavior of the MakeNoise() method.

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

Edit: Looks like Brian beat me to the punch. Funny we used the same example. But the above code should help clarify the concepts.

编辑:看起来布赖恩击败了我。有趣的是,我们使用了相同的示例。但是上面的代码应该有助于澄清概念。

回答by Patrick McElhaney

Both overriding and overloading are used to achieve polymorphism.

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

You could have a method in a class that is overriddenin one or more subclasses. The method does different things depending on which class was used to instantiate an object.

您可以在一个或多个子类中覆盖一个类中的方法。该方法根据用于实例化对象的类执行不同的操作。

    abstract class Beverage {
       boolean isAcceptableTemperature();
    }

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

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

You could also have a method that is overloadedwith two or more sets of arguments. The method does different things based on the type(s) of argument(s) passed.

您还可以拥有一个 重载了两组或更多组参数的方法。该方法根据传递的参数类型执行不同的操作。

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

回答by jpeacock

Neither:

两者都不:

Overloading is when you have the same function name that takes different parameters.

重载是指您具有相同的函数名称但采用不同的参数。

Overriding is when a child class replaces a parent's method with one of its own (this in iteself does not constitute polymorphism).

覆盖是指子类用自己的方法替换父类的方法(这本身并不构成多态性)。

Polymorphism is late binding, e.g. the base class (parent) methods are being called but not until runtime does the application know what the actual object is - it may be a child class whose methods are different. This is because any child class can be used where a base class is defined.

多态是后期绑定,例如,基类(父)方法被调用,但直到运行时应用程序才知道实际对象是什么——它可能是一个方法不同的子类。这是因为可以在定义基类的地方使用任何子类。

In Java you see polymorphism a lot with the collections library:

在 Java 中,您会在集合库中看到很多多态性:

int countStuff(List stuff) {
  return stuff.size();
}

List is the base class, the compiler has no clue if you're counting a linked list, vector, array, or a custom list implementation, as long as it acts like a List:

List 是基类,编译器不知道你是在计算链表、向量、数组还是自定义列表实现,只要它像 List 一样:

List myStuff = new MyTotallyAwesomeList();
int result = countStuff(myStuff);

If you were overloading you'd have:

如果您超载,您将拥有:

int countStuff(LinkedList stuff) {...}
int countStuff(ArrayList stuff) {...}
int countStuff(MyTotallyAwesomeList stuff) {...}
etc...

and the correct version of countStuff() would be picked by the compiler to match the parameters.

并且编译器将选择正确版本的 countStuff() 以匹配参数。

回答by Lorenzo Boccaccia

Polymorphism relates to the ability of a language to have different object treated uniformly by using a single interfaces; as such it is related to overriding, so the interface (or the base class) is polymorphic, the implementor is the object which overrides (two faces of the same medal)

多态性与语言通过使用单个接口统一处理不同对象的能力有关;因此它与覆盖有关,因此接口(或基类)是多态的,实现者是覆盖的对象(同一奖牌的两个面)

anyway, the difference between the two terms is better explained using other languages, such as c++: a polymorphic object in c++ behaves as the java counterpart if the base function is virtual, but if the method is not virtual the code jump is resolved statically, and the true type not checked at runtime so, polymorphism include the ability for an object to behave differently depending on the interface used to access it; let me make an example in pseudocode:

无论如何,使用其他语言(例如 c++)可以更好地解释这两个术语之间的区别:如果基函数是虚拟的,则 c++ 中的多态对象的行为与 java 对应物一样,但如果方法不是虚拟的,则代码跳转将静态解析,并且在运行时没有检查真正的类型,所以多态性包括一个对象根据用于访问它的接口而表现不同的能力;让我用伪代码举个例子:

class animal {
    public void makeRumor(){
        print("thump");
    }
}
class dog extends animal {
    public void makeRumor(){
        print("woff");
    }
}

animal a = new dog();
dog b = new dog();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

(supposing that makeRumor is NOT virtual)

(假设 makeRumor 不是虚拟的)

java doesn't truly offer this level of polymorphism (called also object slicing).

java 并没有真正提供这种级别的多态性(也称为对象切片)。

animal a = new dog(); dog b = new dog();

动物 a = 新狗();狗 b = 新狗();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

on both case it will only print woff.. since a and b is refering to class dog

在这两种情况下,它只会打印 woff .. 因为 a 和 b 是指类狗

回答by The Digital Gabeg

Polymorphismis the ability of a class instance to behave as if it were an instance of another class in its inheritance tree, most often one of its ancestor classes. For example, in Java all classes inherit from Object. Therefore, you can create a variable of type Object and assign to it an instance of any class.

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

An overrideis a type of function which occurs in a class which inherits from another class. An override function "replaces" a function inherited from the base class, but does so in such a way that it is called even when an instance of its class is pretending to be a different type through polymorphism. Referring to the previous example, you could define your own class and override the toString() function. Because this function is inherited from Object, it will still be available if you copy an instance of this class into an Object-type variable. Normally, if you call toString() on your class while it is pretending to be an Object, the version of toString which will actually fire is the one defined on Object itself. However, because the function is an override, the definition of toString() from your class is used even when the class instance's true type is hidden behind polymorphism.

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

Overloadingis the action of defining multiple methods with the same name, but with different parameters. It is unrelated to either overriding or polymorphism.

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