Создание экземпляра конкретного подкласса из метода stati c его абстрактного суперкласса - PullRequest
0 голосов
/ 14 июля 2020

[READ] Мой реальный вопрос заключается в том, как работает метод stati c makeInstance () абстрактного класса Calendar (из java .util)? Я видел такой код:

Calendar cal = Calendar.makeInstance ();

Мне было любопытно, как это работает, поскольку если makeInstance () возвращает объект подкласса Calendar, тогда он должен быть каким-то образом осведомлены о своих подклассах. Конечно, это неправда. Классы знают только своих родителей, но не своих детей. Мне не удалось найти исходный код makeInstance (), мне сказали посмотреть в папку sr c .zip, в которую я установил JDK, но моя ОС сообщила мне, что это символическая ссылка c, а я не умеют просматривать содержимое папки с символическими ссылками. Итак, я попытался сымитировать сценарий, в котором метод суперкласса stati c будет создавать объект подкласса со ссылочным типом суперкласса. В моем основном методе я смоделировал приведенный выше код и попытался использовать и получить доступ к членам подкласса, но безрезультатно.

Вот мой код, в IDE есть волнистые линии под обоими вызовами метода в основном методе.

Подчиненный. java

public class Subordinate extends Superman {
    private String name;

    public void setName(String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }
}

Супермен. java

public abstract class Superman {
    
    public static Superman makeInstance() {
        Superman a = new Subordinate(); 
        return a;
    }
}

TesterClass. java

public class TesterClass {
    public static void main(String args[]) {
        Superman s = Superman.makeInstance(); 
        System.out.println("Testing that instance has been made and members are accessible");
        s.setName("Harry");
        System.out.println(s.getName());
    }
}

1 Ответ

0 голосов
/ 14 июля 2020

Если вы посмотрите на исходный код , вы увидите, что метод stati c создает ссылку null абстрактного суперкласса, который всегда становится спецификацией c реализации Calendar перед возвратом.

Как вы можете видеть в приведенном ниже коде, это предложение относительно отцов, не знающих детей, не совсем верно, и я бы не стал следовать этому правилу при кодировании.

Все методы getInstance() вызывают этот метод в конце, чтобы вернуть Calendar:

private static Calendar createCalendar(TimeZone zone,
                                       Locale aLocale)
{
    Calendar cal = null;

    String caltype = aLocale.getUnicodeLocaleType("ca");
    if (caltype == null) {
        // Calendar type is not specified.
        // If the specified locale is a Thai locale,
        // returns a BuddhistCalendar instance.
        if ("th".equals(aLocale.getLanguage())
                && ("TH".equals(aLocale.getCountry()))) {
            cal = new BuddhistCalendar(zone, aLocale);
        } else {
            cal = new GregorianCalendar(zone, aLocale);
        }
    } else if (caltype.equals("japanese")) {
        cal = new JapaneseImperialCalendar(zone, aLocale);
    } else if (caltype.equals("buddhist")) {
        cal = new BuddhistCalendar(zone, aLocale);
    } else {
        // Unsupported calendar type.
        // Use Gregorian calendar as a fallback.
        cal = new GregorianCalendar(zone, aLocale);
    }

    return cal;
}

Таким образом, он всегда будет возвращать неабстрактную реализацию Calendar , один из этих дочерних элементов:

  • BuddhistCalendar
  • GregorianCalendar
  • JapaneseImperialCalendar

Оба Japanese и Gregorian кажется, что включены в тот же пакет (чтобы отец знал о них), и, как Java 7, им пришлось импортировать календарь Buddhist, как показывает эту строку в исходном коде:

import sun.util.BuddhistCalendar; //lol a sun package

Итак, с этим поведением проблем нет, может быть, просто какой-то бес Орты обязательны. Что касается вашего вопроса, эти три конкретных подкласса инициализируются методом stati c абстрактного суперкласса Calendar, без каких-либо magi c позади ( раньше был iri sh лепрекон делает эти вещи за кулисами, но они удалили это в Java 1.5 ):

 Calendar cal = null; 
 ...
 cal = new GregorianCalendar(zone, aLocale);
 cal = new JapaneseImperialCalendar(zone, aLocale);
 cal = new BuddhistCalendar(zone, aLocale);
...