Java - сделать статический вложенный класс видимым для всех, но только созданным родителем и подклассами родителя - PullRequest
0 голосов
/ 21 мая 2018

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

public abstract class Parent
{
    public static class Data
    {
        public final String data1
        ...

        public Data(String d1, ...)
        {
            data1 = d1;
            ...
        }
    }

    public abstract Data getData();
}

public final class Subclass extends Parent
{
    @Override
    public Data getData()
    {
        return new Data(.....);
    }
}

public class SomeOtherClass
{
    public void someMethod()
    {
        final Data d = new Subclass().getData();
        System.out.println(d.data1);
    }
}

Объявление Data класса protected остановит getData() от правильной работы.Уменьшение модификатора доступа для конструктора Data помешает правильной работе подклассов Parent.Мне нужно что-то вроде protected-by-parent, которое, как я предполагаю, не существует в Java.

Есть ли подходящий обходной путь?Одна возможность, которую я вижу, - это создание protected метода в Parent, который эффективно отражает, вызывает и возвращает из конструктора Data (который будет сделан private).Это, однако, кажется немного грязным;Кто-нибудь знает лучший способ / дизайн?

Ответы [ 2 ]

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

Вы не можете создать конструктор статического члена класса protected для подклассов внешнего класса.Эта выразительность не существует напрямую в языке Java.

Но вы можете сделать конструктор статического члена класса Data private - в этом случае внешний класс все еще может получить к нему доступ.И внешний класс может определять защищенный фабричный метод, который вызывает конструктор Data - делая его protected, он доступен только для самого Parent, подклассов и всех классов в одном пакете (как это всегда имеет место для* Модификатор protected

public abstract class Parent
{
    protected static Data createData(String d1, ...) {
        return new Data(d1, ...);
    }

    public static class Data
    {
        public final String data1
        ...

        private Data(String d1, ...)
        {
            data1 = d1;
            ...
        }
    }

    public abstract Data getData();
}
0 голосов
/ 21 мая 2018

Лучшим решением было бы сделать вложенный класс protected и заставить его реализовать интерфейс public.Только интерфейс будет открыт внешним классам, а сам вложенный класс останется деталью реализации.

public abstract class Parent
{

    public interface Data {
        public String getData1();
    }

    protected static class DataImpl implements Data
    {
        private final String data1;
        ...

        protected DataImpl(String d1, ...)
        {
            data1 = d1;
            ...
        }
        public String getData1(){
            return data1;
        }
    }

    public abstract Data getData();
}

public final class Subclass extends Parent
{
    @Override
    public Data getData()
    {
        return new DataImpl(.....);
    }
}

public class SomeOtherClass
{
    public void someMethod()
    {
        final Data d = new Subclass().getData();
        System.out.println(d.getData1());
    }
}
...