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

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 に答える
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

工場のパターンを見てみましょう。おそらく、ファクトリ メソッドのアクセス修飾子を使ってゲームをプレイして、必要なものに近いものを取得できます。また、ファクトリ メソッド内でリフレクションを操作して、どのパッケージ アクセスが取得するよりも目的に近いものを取得できる場合もあります。

于 2011-03-14T21:48:15.040 に答える
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 に答える