Создать отдельный объект, используя новое ключевое слово - PullRequest
0 голосов
/ 29 мая 2018

Следующий вопрос задается в 4-м раунде интервью директором проекта.

Есть класс А.Любое количество классов может быть получено из A. Ограничения - это любой подкласс, производный от самого A или A, я должен иметь возможность создавать только один объект на класс, используя новое ключевое слово.Если я попытаюсь создать другой объект, он выдаст исключение.

Class B is derived class of A similarly class C, D, E are also derived classes. The number of class is not limited. Any number of classes can be derived.

Класс B является производным классом A, аналогично класс C, D, E также являются производнымиклассы.Количество занятий не ограничено.Может быть получено любое количество классов.

Логика ограничения должна быть внутри иерархии классов, а не внутри основного класса.

Пример кода основного класса.

A obj1 = new A();  // object should create
A obj2 = new A();   // exception should throw
E Obj3 = new E();  //object should create
E obj4 = new E();   //Exception should throw

Ответы [ 3 ]

0 голосов
/ 29 мая 2018

Вы можете использовать статический экземпляр в A, а затем в конструкторе проверить, существует ли экземпляр, и если да, выдается исключение, если он не создает объект.Я предполагаю, что есть только один объект любого класса, который является или A или подклассом A. Если вы хотите сказать, что должен быть только экземпляр для каждого подкласса и A, то вам может потребоваться создать статический HashMapс Именами классов в качестве ключа в A, а затем проверьте, существует ли экземпляр для определенного класса, проверив имя_класса из HashMap.

0 голосов
/ 29 мая 2018

Этого можно добиться, сохранив статическую ссылку на коллекцию, содержащую созданные экземпляры классов (может быть любую работающую структуру данных), а затем проверив ее в конструкторе, чтобы избежать нескольких экземпляров:

class A {
    private static Set<String> instantiatedClasses = new HashSet<>();

    A() {
        super();

        if (instantiatedClasses.contains(getClass().getName())) {
            throw new IllegalStateException(
                    "Cannot create multiple instances of " +getClass().getName());
        }

        instantiatedClasses.add(this.getClass().getName());
    }
}

class B extends A {
}

И когдаэто проверено:

A a = new A();
System.out.println("Created a: " + a);
try {
    a = new A();
} catch (Exception e) {
    e.printStackTrace();
}

a = new B();
System.out.println("Created b: " + a);
a = new B();

Производится такой вывод:

Created a: stackoverflow.A@506e1b77
java.lang.IllegalStateException: Cannot create multiple instances of stackoverflow.A
    at stackoverflow.A.<init>(Main.java:32)
    at stackoverflow.Main.main(Main.java:14)
Created b: stackoverflow.B@9807454
Exception in thread "main" java.lang.IllegalStateException: Cannot create multiple instances of stackoverflow.B
    at stackoverflow.A.<init>(Main.java:32)
    at stackoverflow.B.<init>(Main.java:40)
    at stackoverflow.Main.main(Main.java:21)

Это просто использование факта, что конструктор суперкласса всегда вызывается при создании экземпляра для подклассов.И это будет работать даже для произвольной глубины наследования.

Существуют альтернативные способы отслеживания созданных экземпляров классов, один из которых хранит класс, но я считаю, что необходимая часть проверяет тип вконструктор (где можно увидеть классы времени выполнения и до того, как станет слишком поздно, чтобы предотвратить успешную реализацию)

0 голосов
/ 29 мая 2018

В классе A: есть статический набор классов.Каждый раз, когда вызывается конструктор A, используйте this.getClass () для получения фактического класса, для которого требуется создать экземпляр (имейте в виду, что любой подкласс должен сначала вызывать супер-конструктор).

Есликласс хранится в наборе, брось это исключение.Если нет, то сохраните класс.

public class A {

private static final Set<Class<? extends A>> INSTANCE_HOLDER = new HashSet<>();

public A() {
    if (INSTANCE_HOLDER.contains(this.getClass()))
        throw new RuntimeException("can't create more than one instance.");

    INSTANCE_HOLDER.add(this.getClass());
}
}

Этого должно быть достаточно для начала.

Для справки: хотя это должно сработать, это кажется довольно странной идеей.Если вам нужны одноэлементные объекты, рассмотрите, например, использование перечислений.Это предотвратит все тонкие проблемы, например, из-за создания потоков несколькими объектами.

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

Но, в конце концов, все это звучит как нарушение принципа единой ответственности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...