Можно ли создать экземпляр абстрактного класса?
Во время одного из собеседований мне задали вопрос: "Можно ли создать экземпляр абстрактного класса?"
Мой ответ был "Нет, нельзя". Но интервьюер сказал мне: "Неправильно, мы можем".
Я немного поспорил на эту тему, после чего он предложил мне попробовать это сделать самостоятельно дома.
Вот пример кода:
abstract class my {
public void mymethod() {
System.out.print("Abstract");
}
}
class poly {
public static void main(String a[]) {
my m = new my() {};
m.mymethod();
}
}
В этом коде я создаю экземпляр абстрактного класса my
и вызываю метод абстрактного класса. Можете ли вы объяснить это мне? Действительно ли я был неправ на собеседовании?
5 ответ(ов)
Нет, вы никогда не сможете создать экземпляр абстрактного класса.
Если интервьюер всё равно не согласен, можно сказать:
Вы можете создать анонимный класс.
При этом, анонимный класс объявляется и инстанцируется в одном и том же месте/строке.
Также возможно, что интервьюер захочет проверить вашу уверенность и знание ООП.
Вышеописанное создает анонимный внутренний класс, который является подклассом абстрактного класса my
. Это не совсем эквивалентно инстанцированию самого абстрактного класса. С другой стороны, любой экземпляр подкласса является также экземпляром всех своих суперклассов и интерфейсов, поэтому большинство абстрактных классов действительно инстанцируются путем создания одного из их конкретных подклассов.
Если интервьюер просто сказал "неправильно!" без объяснений и привел этот пример как уникальный контрпример, то, на мой взгляд, он не совсем понимает, о чем говорит.
= my() {};
означает, что здесь происходит анонимная реализация, а не простая инстанциация объекта, которая должна была бы выглядеть как = my()
. Вы никогда не сможете создать экземпляр абстрактного класса.
Вот наблюдения, которые можно сделать:
- Почему
poly
extendsmy
? Это бесполезно... - Каков результат компиляции? Три файла:
my.class
,poly.class
иpoly$1.class
. - Если мы можем создать экземпляр абстрактного класса таким образом, то мы также можем создать экземпляр интерфейса... странно...
Можем ли мы создавать экземпляры абстрактного класса?
Нет, не можем. Что мы можем сделать, так это создать анонимный класс (это третий файл) и создать его экземпляр.
Что насчет инстанцирования суперкласса?
Абстрактный суперкласс инстанцируется не нами, а Java.
EDIT: Попросите его протестировать это
public static final void main(final String[] args) {
final my m1 = new my() {
};
final my m2 = new my() {
};
System.out.println(m1 == m2);
System.out.println(m1.getClass().toString());
System.out.println(m2.getClass().toString());
}
Вывод будет:
false
class my$1
class my$2
Технический ответ
Абстрактные классы не могут быть инстанциированы — это определение и особенность их дизайна.
Согласно JLS, Глава 8. Классы:
Именованный класс может быть объявлен абстрактным (§8.1.1.1), и должен быть объявлен абстрактным, если он неполностью реализован; такой класс не может быть инстанциирован, но может быть расширен подклассами.
Из документации JSE 6 по методу Classes.newInstance():
InstantiationException — если этот класс представляет собой абстрактный класс, интерфейс, массив, примитивный тип или void; или если у класса нет конструктора без параметров; или если инстанциирование завершается неудачей по какой-либо другой причине.
Вы, конечно, можете создать экземпляр конкретного подкласса абстрактного класса (включая анонимный подкласс) и также произвести приведение типа объекта к абстрактному типу.
Другой угол зрения — Командная работа и социальный интеллект:
Подобные технические недопонимания часто происходят в реальной жизни, когда мы имеем дело со сложными технологиями и юридически строгими спецификациями.
«Навыки общения» могут быть здесь важнее, чем «технические навыки». Если вы будете агрессивно пытаться доказать свою правоту, то теоретически вы можете оказаться правы, но это может нанести гораздо больше вреда в виде конфликта или ухудшения отношений, чем стоит. Будьте примирительными и понимающими в разрешении ваших разногласий. Кто знает — возможно, вы оба правы, просто опираясь на слегка разные значения терминов?
Неизвестно — хотя и маловероятно, что интервьюер намеренно создал небольшое недопонимание, чтобы поставить вас в сложную ситуацию и посмотреть, как вы будете реагировать эмоционально и социально. Будьте тактичными и конструктивными с коллегами, следуйте советам более опытных людей и поддерживайте связь после интервью, чтобы разрешить любые недоразумения — по электронной почте или телефону. Это покажет вашу заинтересованность и внимание к деталям.
Почему классы в Python наследуют от object?
Понимание Python super() с методами __init__()
Когда использовать 'self' вместо '$this'?
Что значит "Не удалось найти или загрузить основной класс"?
Как скопировать объект в Java?