Переопределение-перегрузка функции в Java - PullRequest
10 голосов
/ 12 января 2010

В чем разница между переопределением и перегрузкой?

Ответы [ 6 ]

22 голосов
/ 12 января 2010
  • Перегрузка: выбор метода подпись во время компиляции на основе количества и типа указанных аргументов

  • Переопределение: выбор метода реализация во время выполнения на основе фактического типа целевого объекта (в отличие от типа выражения во время компиляции)

Например:

class Base
{
    void foo(int x)
    {
        System.out.println("Base.foo(int)");
    }

    void foo(double d)
    {
        System.out.println("Base.foo(double)");
    }
}

class Child extends Base
{
    @Override void foo (int x)
    {
        System.out.println("Child.foo(int)");
    }
}

...

Base b = new Child();
b.foo(10); // Prints Child.foo(int)
b.foo(5.0); // Prints Base.foo(double)

Оба вызова являются примерами перегрузки . Существует два метода с именем foo, и компилятор определяет, какую подпись вызывать.

Первый вызов является примером переопределения . Компилятор выбирает сигнатуру "foo (int)", но затем во время выполнения тип целевого объекта определяет, что используемая реализация должна быть такой же, как в Child.

10 голосов
/ 12 января 2010
  • Перегрузка методов - это трюк компилятора, позволяющий использовать одно и то же имя для выполнения различных действий в зависимости от параметров.

  • Переопределение метода означает, что весь его функционал заменяется. Переопределение - это то, что делается в дочернем классе для метода, определенного в родительском классе.

Источник: http://www.jchq.net/tutorial/06_02Tut.htm

6 голосов
/ 12 января 2010

Перегрузка:

public Bar foo(int some);
public Bar foo(int some, boolean x);  // Same method name, different signature.

Переопределение:

public Bar foo(int some);   // Defined in some class A
public Bar foo(int some);   // Same method name and signature. Defined in subclass of A.

Если бы второй метод не был определен, он унаследовал бы первый метод. Теперь он будет заменен вторым методом в подклассе A.

4 голосов
/ 12 января 2010

Перегрузка - похожая подпись - то же имя, разные параметры

void foo() {
   /** overload */
}

void foo( int a ) {
   /** overload */
}

int foo() {
   /** this is NOT overloading, signature is for compiler SAME like void foo() */
}

Переопределить - вы можете переопределить тело метода, когда наследуете его.

class A {
   void foo() {
      /** definition A */
   }
}

class B extends A {
   void foo() {
      /** definition B, this definition will be used when you have instance of B */
   }
}
2 голосов
/ 03 февраля 2010

На интересную вещь, чтобы упомянуть:

public static doSomething(Collection<?> c) {
    // do something
}

public static doSomething(ArrayList<?> l) {
    // do something
}

public static void main(String[] args) {
    Collection<String> c = new ArrayList<String> ();
    doSomething(c); // which method get's called?
}

Можно предположить, что метод с аргументом ArrayList будет вызван, но это не так. Первый метод вызывается, поскольку правильный метод выбран во время компиляции.

1 голос
/ 12 января 2010

Override

Когда метод, унаследованный подклассом от суперкласса, заменяется (переопределен) в подклассе.

class A {
  void foo() {
    /** definition A of foo */
  }
}

class B extends A {
  void foo() {
    /** definition B of foo */
  }
}

Теперь, если вы позвоните foo, используя:

A a = new B();
a.foo();

Будет выполнено определение B для foo. Это не так интуитивно понятно, поскольку вы получите ошибку компиляции, если в классе A не было метода с именем foo. Таким образом, тип объекта a, который является A, должен иметь метод foo, тогда вы можете вызывать его и метод foo экземпляра будет выполнено, то есть класса B, следовательно, 'время выполнения'.

Перегрузка

Когда вы создаете метод с тем же именем, что и существующий метод. Чтобы избежать ошибки времени компиляции, у вас есть для определения нового метода с параметрами, отличными от существующего. Таким образом, методы будут различимы. Имейте метод с тем же именем и параметрами, но другой тип возвращаемого значения все еще неопределенный и, следовательно, приведет к ошибке компиляции. Пример перегрузки:

class A {
  void bar(int i) {}
  // The following method is overloading the method bar
  void bar(Object a) {}
  // The following will cause a compile error. 
  // Parameters should differ for valid overload
  boolean bar(int i) {
    return true;
  }
}
...