Выполнил всё в соответствии с требованиями, код работает и валидацию прошел. Вот только нет понимания одного нюанса.
Я помню, что создать объект(экземпляр) на основе абстрактного класса нельзя. Помню так же, что любой класс и его статические методы хранятся в памяти в единственном экземпляре. А НЕ статические поля и методы относятся уже уже к объекту (экземпляру) класса создаваемого командой new. А что же из себя представляет не статическое поле абстрактного класса, если объекта (экземпляра) класса нет и быть не может?
public class Solution {
public static void main(String[] args) {
Person ivan = new Person("Иван");
ivan.allMoney.add(new Hryvnia(100000));
ivan.allMoney.add(new USD(10000));
ivan.allMoney.add(new Ruble(1000000));
for (Money money : ivan.getAllMoney()) {
System.out.println(ivan.name + " имеет заначку в размере " + money.getAmount() + " " + money.getCurrencyName());
}
}
---------------------------------------------------------------------
public abstract class Money {
public Money(double amount) {
this.amount = amount;
}
private double amount;
---------------------------------------------------------------------
public class USD extends Money {
public USD(double amount){
super(amount);
}
public String getCurrencyName(){
return "USD";
}
}
NightCrow
27 уровень
Super(amount) - если объекта класса нет, то где это?
Решен
Комментарии (5)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
KIRAРазработчик в prosv.ruExpert
28 октября 2024, 07:14
Это гарантированное поле которое будет у любого класса наследника. Аналогично и с не статическими методами (абстрактными или нет). Вы указываете какие методы будут и пишите к ним реализацию (или нет делая абстрактными) и любой класс наследник сможет их использовать.
Super(amount) - если объекта класса нет, то где это?
Смысл абстрактного класс - это создать шаблон для наследников. Именно по этому нельзя указать абстрактный класс как final, иначе в нем не будет смысла
0
NightCrowSystem Engineer в Аплана
28 октября 2024, 08:57
Я не о том спрашивал (ну или не понял ответа, допускаю и такое). Вопрос не в том, для чего нужен абстрактный класс, а в том, что мы передали в нестатическую переменную абстрактного класса несколько значений (создавая объекты класса потомка и вызывая конструктор родительского абстрактного класса). Раз несколько значений, то это не в области памяти, в которой находится сам класс (да и переменная не статическая, в любом случае). Раз это не в этой области памяти, а экземпляров абстрактного класса не существует, то где? Могу предположить, что в реальности значение пошло в переменную экземпляра класса наследника. Но и это не очень понятно.
0
hidden #3303140
28 октября 2024, 09:13решение
Этот ответ как раз о том, о чём ты спрашивал. Потому что твой вопрос говорит именно о том, что ты не до конца понимаешь предназначения абстрактного класса.
Переменная amount объявлена в абстрактном классе, значит она будет существовать у всех инстансов дочерних классов. Да, объект абстрактного класса создать нельзя, но можно создать объект его наследника, что ты в методе main и делаешь:
Здесь не создаётся двух инстансов - Money и USD, а создаётся только инстанс класса USD. Но по спецификации языка, чтобы создать инстанс наследника, сначала обязательно нужно выполнить конструктор всех его родителей по цепочке до самого старшего, именно поэтому конструкторы наследников обязаны начинаться с команды super(). И поскольку USD наследуется от Money, то в этом инстансе как раз и будет содержаться поле amount, а заполняться оно будет именно при выполнении тела конструктора родителя.
То есть конструктор родителю нужен не для того, чтобы создать инстанс этого (родительского) класса, а для того, чтобы выполнить все операции, которые в нём описаны, и дальше перейти к созданию инстанса наследника.
И ещё маленькое уточнение о полиморфизме. Возможно, это тебе уже и без него понятно, но на всякий случай приведу. Вот рассмотрим опять ту же конструкцию:
Здесь объект типа USD сохранён в переменную типа Money. Тип переменной - Money - отвечает за то, какие методы будут доступны для вызова у объекта oneDollar. А класс объекта - USD - отвечает за то, каким образом эти методы будут исполняться. То есть тип переменной отвечает за сигнатуру его публичных методов и полей, а класс объекта отвечает за тело (содержание) этих методов.
+2
NightCrowSystem Engineer в Аплана
28 октября 2024, 10:19
Товарисч, перелогиньтесь, у вас под этим ником уровень 2. ))))
А если серьезно, то я в тексте выше все же предположил, что значение идет в соответствующую переменную потомка, но одно дело предполагать, другое понимать механизм.
ОК. Ну а заполнение переменной через конструктор родителя (а не напрямую в объекте потомка), это уже вопрос обеспечения полиморфизма и инкапсуляции, так?
+2
KIRAРазработчик в prosv.ruExpert
28 октября 2024, 15:26
Если считаете, что ответ не о том, попробуйте перефразировать вопрос. Возможно Вас не поняли.
Объект после создания хранится в куче (heap)
Информация о загруженных классах хранится в Metaspace
Метаданные хранят:
1. Имена классов и пакетов
Полное имя класса, включая пакет, например, com.example.MyClass.
Имя пакета, например, com.example.
2. Описание методов
Название метода.
Тип возвращаемого значения.
Список параметров и их типы.
Модификаторы доступа (например, public, private, protected).
Исключения, которые метод может выбросить.
3. Описания полей
Названия полей.
Их типы.
Значения по умолчанию (для статических полей).
Модификаторы (например, static, final).
4. Конструкторы
Описание конструкторов класса, аналогичное методам, но без указания возвращаемого типа.
5. Интерфейсы и суперклассы
Указание, какие интерфейсы реализует данный класс и от какого суперкласса он наследуется.
6. Аннотации
Вся информация об аннотациях, применяемых к классам, методам и полям, включая параметры аннотаций.
7. Типы generic
Параметры обобщенного типа (generics), применяемого к классу или методу.
8. Атрибуты классов
Дополнительные атрибуты, такие как версия JVM, на которой был скомпилирован класс, и другая служебная информация.
0