Переопределение-перегрузка функции в Java

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

6 ответов

Решение
  • Перегрузка: выбор сигнатуры метода во время компиляции на основе количества и типа указанных аргументов.

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

Например:

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,

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

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

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

Перегрузка:

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.

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

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 */
   }
}

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

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 будет вызван, но это не так. Первый метод вызывается, так как правильный метод выбран во время компиляции.

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;
  }
}
Другие вопросы по тегам