0

这可能是不可能的,但我正在尝试创建一个只有共享超类的类才能访问的构造函数,这几乎是受保护修饰符的反向逻辑。我假设没有修饰符可以直接完成此操作,但是知道我要完成什么,有什么建议吗?

public Account extends SomeEntity {

    //default public
    public Account() {

    }

    // I am wanting this constructor to be only available to sibling classes.
    // (those that share the same super class )
    <modifier> Account(Element accountElement) {

    }
}


public Accounts extends SomeEntity {

    private List<Account> accountList;

    //default public
    public Accounts() {

        Account newAcct = new Account(element);

        //looped loading up Generic list of Account
        this.accountList.add(newAcct);
    }

我正在使用 RESTful Web 服务并从 XML 响应中构建对象,问题是如果我GET将帐户列表构建到帐户对象列表中,我将不得不查询每个单独帐户的 Web 服务,即使我已经有了信息,这似乎完全没有效率。

我不想让我正在构建的 API 的普通用户能够以这种方式实例化帐户对象。(带Element

4

7 回答 7

3

没有这样的语言结构。从 1.6 开始,包(=默认)访问是镇上唯一的 Java 机制。

我相信你可以用堆栈做一些讨厌的事情,但我不会推荐它们。

于 2011-03-14T21:42:35.193 回答
1

我会看看工厂模式。您可能可以使用工厂方法的访问修饰符玩游戏以获得接近您想要的东西。您可能还可以在工厂方法中使用反射来获得比包访问更接近您想要的东西。

于 2011-03-14T21:48:15.040 回答
1

对不起,但我仍然不明白这个设计的意义。如果一个方法被添加到一个类,它的实现可能只使用这个类的私有数据,因此不能保证“兄弟”类也可以使用这些数据。换句话说,如果您的愿望得到满足,您如何保证构造函数 Account(Object arg0) 实现不会将私有数据用于 Account 类?(因此对 Accounts 类不可见)

在我看来,您希望您的代码为单个帐户和帐户列表提供相同的接口 - 扩展 SomeEntity 类。这可以通过复合模式更优雅地完成。

http://en.wikipedia.org/wiki/Composite_pattern

但是,如果您的意图是提供一个只有子类会使用的自定义构造函数,为什么不在 SomeEntity 中声明自定义构造函数并使这个类抽象呢?

另外,请记住您可以这样做:

public Account() {
  this(new arg0());
}

Account(Object arg0) {

}

不过,不确定这是否有帮助。

于 2011-03-14T22:00:05.097 回答
1

有一种方法可以模拟 C++ 的朋友功能,从而达到您想要的结果。

警告:这是一种人为的技术,只有在您没有其他解决方案时才应使用!

由于在这种情况下没有修饰符可以满足您的要求,因此诀窍是将访问限制移动到另一个应用修饰符的地方。为此,向构造函数添加一个关键参数。该键属于只能由允许的“兄弟”类(即给定类的子类)实例化的类。

因此,该限制被移至公共超类,在该超类中,可以使用通常的修饰符来限制键的创建。

这是一个例子:

public class CommonSuperClass {
    public static final class Key {
        private Key() {}
    }

    // This is the only way to create a key, and it's protected
    protected final Key createKey() {
        return new Key();
    }
}

public class Account {
    // The restricted constructor can even be public
    public Account(Key key) {
        // Everybody can try with null, but we're not that stupid
        // Of course any RuntimeException can be thrown instead
        if (key == null) throw new UnsupportedOperationException();
    }
}

public class AllowedSibling extends CommonSuperClass {
    public void foo() {
        // I'm allowed
        new Account(this.createKey());
    }
}

public class DeniedClass {
    public void foo() {
        // This doesn't compile
        new Account(new Key());

        // This will throw an exception
        new Account(null);
    }
}
于 2011-03-14T22:12:16.963 回答
0

这是一个非常奇怪的必要条件,我认为没有访问修饰符可以做你想做的事。无论如何,我建议您将构造函数公开并将它们记录为“仅供内部使用”。

如果你真的需要限制访问,你可以使用这个冗长的解决方案:

public class Base {
    protected interface Factory {
        Base getInstance(Element e);
    }

    private static Map<Class<?>, Factory> registry = new HashMap<Class<?>, Factory>();
    protected static void register(Class<?> c, Factory f) { registry.put(c, f); }
    protected static <T extends Base> T create(Class<T> c, Element e) {
        return (T) registry.get(c).getInstance(e);
    }
}

public class Derived1 extends Base {
    protected Derived1(Element e) { }
    private static class Derived1Factory implements Factory {
        public Derived1 getInstance(Element e) {
            return new Derived1(e);
        }
    }

    static {
        register(Derived1.class, new Derived1Factory());
    }
}

public class Derived2 extends Base {
    protected Derived2(Element e) { }
    private static class Derived2Factory implements Factory {
        public Derived2 getInstance(Element e) {
            return new Derived2(e);
        }
    }

    static {
        register(Derived2.class, new Derived2Factory());
    }

    public void method() {
        Element e = null;
        ...
        // Put some element in e
        ...
        // This is what you were trying to do
        Derived1 d1 = create(Derived1.class, e);
    }
}
于 2011-03-14T22:50:08.633 回答
0
public class SomeEntity
    protected void init(Element accountElement) {}

public class Account extends SomeEntity 

    public Account() 
        ....

    protected void init(Element accountElement)
        ....


public class Accounts extends SomeEntity

    Account newAcct = new Account();
    newAcct.init(element);
于 2011-03-14T23:13:42.037 回答
-1

这是我会尝试的(我没有测试过这种方法):

<modifier> Account(Object arg) {
    if (!super.getClass().isAssignableFrom(this.getClass())) {
        throw new AssertionError("This constructor is only available to super classes.");
    } else {
        // Continue...
    }
}
于 2011-03-14T21:49:05.743 回答