【问题标题】:Java - make static nested class visible to all, but only constructed by parent and subclasses of parentJava - 使静态嵌套类对所有人可见,但仅由父类和父类的子类构造
【发布时间】:2018-10-30 20:53:36
【问题描述】:

我有一个包含类似结构的静态嵌套类的父类。嵌套类必须是公共的,因为它应该返回到对其内容进行操作的其他类。但是,只有父类及其子类应该能够实例化嵌套类,因为它们知道如何定义其内容。下面显示的所有类都在不同的包中。

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);
    }
}

声明Dataprotected 将阻止getData() 正常工作。减少Data 的构造函数上的访问修饰符将阻止Parent 的子类正常工作。我想要的是像protected-by-parent 这样的东西,我猜Java 中不存在。

是否有合适的解决方法?我可以看到的一种可能性是在Parent 中创建一个protected 方法,该方法有效地从Data 的构造函数(将被设为private)进行镜像、调用和返回。然而,这似乎有点混乱。有人知道更好的方法/设计吗?

【问题讨论】:

    标签: java inner-classes access-modifiers


    【解决方案1】:

    更好的解决方案是使嵌套类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());
        }
    }
    

    【讨论】:

    • 这看起来不错。它似乎本质上更像是聪明的 OOP 设计,但我很难看出它在功能方面对提议的解决方案的实际改进之处。您能否详细说明为什么这是一个更好的解决方案?
    • @ChristopherRiches 它允许您从SomeOtherClass 隐藏嵌套类(我将其重命名为DataImpl),从而阻止SomeOtherClass 创建该类的实例,同时仍然允许SomeOtherClass访问Data 实例的内容(通过接口)。我编辑了答案以使DataImpl 构造函数也protected
    • 我的观点是:受保护的工厂方法也可以用更少的代码实现这一点。除此之外,你的方法还有什么作用吗?
    【解决方案2】:

    您不能为外部类的子类创建静态成员类protected 的构造函数。这种表现力并不直接存在于 Java 语言中。

    但是,你可以让静态成员类Dataprivate的构造函数——在这种情况下,外部类仍然可以访问它。并且外部类可以定义一个受保护的工厂方法来调用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();
    }
    

    【讨论】:

    • 这就是我在问题最后一段中的建议。不过,感谢您提供示例。
    • 我现在明白了。你为什么称它为“乱七八糟”?
    • 我想混乱不是正确的词。我的意思是,它看起来有点像一种糟糕的笨拙的hack,尽管它可能很好。查看涉及公共接口的受保护实现的其他解决方案,这实际上看起来不那么“混乱”。任何人都可以评论两者的优缺点吗?
    • 在没有进一步证据表明另一种方法更好的情况下,我将此标记为已接受的答案,因为它是我目前正在使用的答案。
    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 2011-06-09
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    • 2021-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多