重新定义方法和覆盖方法之间有什么区别?

class DonkeyBattler { static void doBattle(){ System.out.println("Weaponized donkey battling"); } } class FunkyBattler extends DonkeyBattler { static void doBattle(){ System.out.println("Weaponized donkey battling with bellbottoms"); } } 

doBattle方法应该是重新定义还是覆盖? 哦顺便说一句,这是Java。

关于Java方法和inheritance,通常不使用术语“重定义”。 通常使用两个术语:如你所说的“覆盖”和“超载”。 在Java中重载是在同一个类中创建两个具有相同名称但签名不同的方法(参数的数量和/或类型)。 例如:

 public interface MyInterface { public int doStuff(int first, int second); public int doStuff(double only); } 

要覆盖的是执行类似于您在示例中所执行的操作:使用与父类中的方法具有相同名称签名的方法创建子类,该方法将用于子类的所有实例但不是父类或该父类的任何其他子类。

您的示例与重载相关的唯一问题是使用关键字static 。 覆盖是动态确定的,但静态方法不是。

我从来没有听说过“重新定义”作为适用于Java的OO术语。

但是,您提供的示例不是重写,因为静态方法不是inheritance的,而是基于变量的类型静态分派(与成员方法发生的动态分派相反)。

我不会称之为重新定义 – 你有一个名为DonkeyBattler.doBattle的方法,你现在已经定义了一个名为FunkyBattler.doBattle的编译独立方法。

覆盖的意图实际上是从父类重新定义inheritance的方法。

重新定义涉及:

  1. 替换

     1. **Replacement** is the case in which child class is overriding 

    具有行为(function)的父类的inheritance方法与对应的父方法完全不同,并且该方法的符号不是在子方法体中调用super.method()。

  2. 精致

     2. Refinement is the case in which child is overriding inherited 

    来自父级的方法具有与父方法function相关的function,此过程的标志通常在子方法的主体中调用super.method()。

一个方法只能在同一个类中重载是完全错误的概念。 相反,方法也可以在子类中重载。

覆盖和重新定义(也称为隐藏)几乎是一些东西,除了:

覆盖是例如方法,重新定义或隐藏是用于类方法。 仅在静态方法的情况下重新定义,因为静态方法没有运行时多态性。

请参阅以下代码以获得澄清:

 class Foo { public static void classMethod() { SOP("classMethod() in Foo"); } public void instanceMethod() { SOP ("instanceMethod() in Foo"); } } class Bar extends Foo { public static void class Method() { SOP ("classMethod() in Bar"); } public void instanceMethod() { SOP ("instanceMethod() in Bar"); } } class Test { public static void main(String[] args) { Foo f = new Bar(); f.instanceMethod(); f.classMethod(); } } 

此代码的输出为:Foo中Bar classMethod()中的instanceMethod()

此输出的原因:

由于instanceMethod()是一个实例方法,其中Bar从Foo覆盖该方法,因此在运行时JVM使用实例f的实际类来确定要运行的方法。 虽然f被声明为Foo,但我们创建的实际实例是一个新的Bar()。 因此,在运行时,JVM发现f是一个Bar实例,因此它调用Bar中的instanceMethod()而不是Foo中的实例。

使用classMethod(),因为它是一个类方法,编译器和JVM不希望需要一个实际的实例来调用该方法。 即使你提供了一个,JVM也永远不会看到它。 编译器只会查看引用的声明类型,并使用该声明的类型在编译时确定要调用的方法。 由于f被声明为Foo类型,编译器会查看f.classMethod()并确定它意味着Foo。 类方法。 f引用的实例实际上是一个Bar并不重要 – 对于静态方法,编译器只使用声明的引用类型。

这就是为什么我在开始时说静态方法没有运行时多态性。

重新定义对Java有效,适用于静态方法。 如果要更改静态方法对类的作用,可以重新定义它。 这不受多态性的影响,因为它不适用于静态方法。

使用您的示例,对类名称或所有子类的所有调用都将获得原始的doBattle( )方法。 对FunkyBattler.doBattle()特定调用将调用FunkyBattler类中重新定义的静态方法。

你有方法“doBattle”静态的并且在Java中静态方法不能被覆盖,这并不意味着它们不能在子类中重新定义,因此这里你重新定义了FunkyBattler类中的方法doBattle DonkeyBattler的子类

  public class Animal{ public static void doStuff(){ System.out.println("In animal"); } } public class Dog extends Animal { //redifinition of the method, since it is... Static static void doStuff() { System.out.println("In Dog..."); } public static void main(String[] args) { Animal animal = new Dog(); animal.doStuff(); } } 

输出将是’动物’,即使你调用静态方法引用Dog,你应该推断出运行时多态性不像OVERRIDING那样工作。

重新定义和覆盖在相同的场景中提供。 唯一不同的是,如果使用的方法是静态,则重新定义。

例如:

重写:

  Class A{ public void show(){ SOP("class a"); } } Class B extends A{ public void show(){ SOP("class B"); } } 

重新定义:

  Class A{ public static void show(){ SOP("class a"); } } Class B extends A{ public static void show(){ SOP("class B"); } } 

注意:静态方法看起来好像被过度使用,但它们实际上是重新定义的。

  1. 使用静态方法重新定义。
  2. 静态方法与Class相关联而不与Object相关联,因此我们不会根据运行时的实例重写。
  3. 在静态的情况下,我们只是重新定义方法。