В чем разница между переопределением и перегрузкой?
Перегрузка переопределения функций в Java
Ответ 1
-
Перегрузка: выбор метода подпись во время компиляции на основе количества и типа указанных аргументов
-
Переопределение: выбор метода во время выполнения на основе фактического типа целевого объекта (в отличие от типа выражения времени компиляции)
Например:
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
.
Ответ 2
-
Перегрузка методов - это трюк компилятора, позволяющий использовать одно и то же имя для выполнения разных действий в зависимости от параметров.
-
Переопределение метода означает, что вся его функциональность заменяется. Переопределение - это что-то сделано в дочернем классе методу, определенному в родительском классе.
Ответ 3
Перегрузка:
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
Перегрузка - аналогичная подпись - то же имя, разные параметры
void foo() {
/** overload */
}
void foo( int a ) {
/** overload */
}
int foo() {
/** this is NOT overloading, signature is for compiler SAME like void foo() */
}
Override - вы можете переопределить тело метода, когда вы наследуете его.
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 */
}
}
Ответ 5
Интересно отметить:
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 called?
}
Можно предположить, что метод с аргументом ArrayList будет вызван, но это не так. Первый метод вызывается, так как правильный метод выбирается во время компиляции.
Ответ 6
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;
}
}