Как работает upcast в данном примере?

Допустим, у нас есть на коленке написанное приложение-магазин, где общий класс, который наследуют все продукты, выглядит так:

public class Product {
public static ArrayList<Product> productsList = new ArrayList<Product>();
String name, manufatcurer; float price;
public Product(String name, String manufatcurer, float price) {
    this.name = name; this.manufatcurer = manufatcurer; this.price = price;
    productsList.add(this);
}}

И затем в наш недомагазин мы добавили два типа продуктов: шоколадка и напиток, которые описаны следующим образом:

public class Chocolate extends Product {
String size;
public Chocolate(String name, String manufatcurer, String size, float price) {
    super(name, manufatcurer, price); this.size = size;
}}

public class Drink extends Product {
String composition;
public Drink(String name, String manufatcurer, String composition, float price) {
    super(name, manufatcurer, price); this.composition = composition;
}}

Вроде всё прекрасно работает, но у меня возникли некоторые непонятки с тем, как происходит upcast во время добавления объектов дочерних типов в ArrayList типа Product. Для начала создадим пару экземпляров класса, чтобы хотя бы иметь то, с чем будем работать:

Chocolate myChocolate = new Chocolate("Mars", 
                                    "Mars Incorporated", 
                                    "small", 
                                    2000.0f);
Drink myDrink = new Drink("Coca-Cola Vanila", 
                        "The Coca-Cola Company", 
                        "Подсолнечное масло и вода", 
                        12000.0f);

После этого попробуем вывести поле "size" у объекта myChocolate через ArrayList:

System.out.println(Product.productsList.get(0).size);

Получим по лицу исключением:

error: cannot find symbol
            System.out.println(Product.productsList.get(0).size);
                                                          ^
symbol:   variable size
  location: class Product
1 error
error: compilation failed

И то же самое будет, если попробуем обратиться к полю "composition" объекта myDrink через тот же список:

System.out.println(Product.productsList.get(1).composition);

Вывод:

error: cannot find symbol
            System.out.println(Product.productsList.get(1).composition);
                                                          ^
symbol:   variable composition
  location: class Product
1 error
error: compilation failed

Из этого можно сделать вывод, что объекты классов "Drink" и "Chocolate" были приведены к материнскому типу "Product". В подтверждении этого я решил вывести типы этих объектов через тот же список:

    for (int i = 0; i < Product.productsList.size() ; i++ ) {
        System.out.println(Product.productsList.get(i).getClass());
    }

...но получил не то, что ожидал:

class Chocolate
class Drink

Вроде бы с помощью upcasta в ArrayList'e я привёл объекты классов к их материнскому типу, но при этом функция .getClass() возвращает мне не класс Product, а именно те классы, экземплярами которых и являются объекты, записанные в списке. Возникает вопрос: почему? Может я просто неправильно понимаю upcast, или в примере выше его вообще не было? В общем, с нетерпением жду ответов. Заранее спасибо всем за уделённое время.


Ответы (0 шт):