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

时间:2011-01-28 17:24:26

标签: java

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。

9 个答案:

答案 0 :(得分:12)

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

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

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

答案 1 :(得分:6)

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

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

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

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

答案 2 :(得分:3)

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

重新定义涉及:

  1. 替换

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

    具有行为(功能)的父类的继承方法与相应的父方法完全不同,并且这个过程的符号不是在子方法体中调用super.method()。

  2. 细化

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

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

答案 3 :(得分:2)

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

答案 4 :(得分:2)

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

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

请参阅以下代码以澄清:

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

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

此输出的原因:

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

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

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

答案 5 :(得分:0)

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

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

答案 6 :(得分:0)

你有方法“doBattle”这是静态并且在Java静态方法中无法覆盖,这并不意味着它们不能在子类中重新定义,因此,您要在 FunkyBattler 类中重新定义 doBatler 方法 DonkeyBattler

的子类

答案 7 :(得分:0)

    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一样工作。

答案 8 :(得分:-1)

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

例如:

<强>重写:

    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. 如果是静态,我们只是重新定义方法。