2

問題

Javaジェネリックを使用して、クラスを同様のメソッドに置き換えようとしています。私が見つけたすべての例は単純な例をカバーしていますが、Java Generics がこのように使用されることを意図しているかどうかはわかりません。

2 つの親クラスと、ほぼ同じメソッドを持つ 2 つの子クラスがあります。両方の親クラスも異なるクラスから派生します。最終的には、コードの 1 つのブロックを使用して親クラスの 1 つを作成および操作し、次にその子クラスを多くの switch ステートメントや重複コードを使用したフロー制御なしで作成および操作できるようにしたいと考えています。

これは、構文であろうとジェネリックの機能ではないことであろうと、まだこの方法で動作させることができていませんが、私が念頭に置いていたことです。

親クラス

public class FooParent
{
    private FooChild fooChild;
    public FooChild getChild()
    {
        return fooChild;
    }
}

public class BarParent
{
    private BarChild barChild;
    public BarChild getChild()
    {
        return barChild;
    }
}

子クラス

public class FooChild
{
    public void print()
    {
        System.out.println("I'm a foo child");
    }
}

public class BarChild
{
    public void print()
    {
        System.out.println("I'm a bar child");
    }
}

ジェネリック クラス

public class GenericParent<T>
{
    private T self;
    public GenericParent(T self)
    {
        this.self = self;
    }

    public GenericChild getChild()
    {
        return new GenericChild(self.getChild());
    }
}

public class GenericChild<T>
{
    private T self;
    public GenericChild(T self)
    {
        this.self = self;
    }

    public void print()
    {
        self.print();
    }
}

どのように使いたいか

public static void main(String args[])
{
    GenericParent parent;

    // Only the initialization of the parent variable needs specialized code
    switch(args[0])
    {
        case "foo":
            parent = new GenericParent(new FooParent());
        break;

        case "bar":
            parent = new GenericParent(new BarParent());
        break;
    }

    // From here on out, it's all generic
    parent.getChild().print();
}

使用法と望ましい出力

java genericExample foo
> I'm a foo child

java genericExample bar
> I'm a bar child

最終質問

「子」と「親」は、実際には継承されていないことを知っているため、誤称かもしれませんが、結論として、1 つのクラスは特定のメソッドで「子」を返します。したがって、これは実際にはこの方法では解決できない可能性がある問題の多くのコードですが、うまくいけば、これに答えていただけます。

  1. これは Java Generics で達成できることですか?
  2. そうでない場合、Java でこの問題の解決策はありますか?

ありがとう!

編集

私の「Foo」と「Bar」クラスは編集できません。私の最終的な質問は、共通の親クラスを使用せずに、いずれかのクラスの 1 つのインスタンスを単一の変数に格納できますか?

4

4 に答える 4

3

I think you want polymorphism, not generics:

public class test {
    public class FooParent implements hasPrintableChildren
    {
        private FooChild fooChild;
        public FooChild getChild()
        {
            return fooChild;
        }
    }

    public class BarParent implements hasPrintableChildren
    {
        private BarChild barChild;
        public BarChild getChild()
        {
            return barChild;
        }
    }


    public class FooChild implements canPrint
    {
        public void print()
        {
            System.out.println("I'm a foo child");
        }
    }

    public class BarChild implements canPrint
    {
        public void print()
        {
            System.out.println("I'm a bar child");
        }
    }

    public interface hasPrintableChildren{
        public canPrint getChild();
    }
    public interface canPrint{
        public void print();
    }



    public static void main(String args[])
    {
        hasPrintableChildren parent;
        // Only the initialization of the parent variable needs specialized code
        switch(args[0])
        {
            case "foo":
                parent = new FooParent();
            break;

            case "bar":
                parent = new BarParent();
            break;
        }

        // From here on out, it's all generic
        parent.getChild().print();
    }
}

OP clarified that he would be interested in the reflection option:

    public static void main(String args[]) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException
    {
        Object parent;
        // Only the initialization of the parent variable needs specialized code
        switch(args[0])
        {
            case "foo":
                parent = new FooParent();
            break;

            case "bar":
                parent = new BarParent();
            break;
        }

        // From here on out, it's all generic
        Object child = parent.getClass().getMethod("getChild").invoke(parent);
        child.getClass().getMethod("print").invoke(child);
    }

Note: I would not recommend this sort of hard coded reflection. Code like this generally stinks of a bigger design problem.

于 2014-05-27T17:42:10.807 に答える
0

はい、ジェネリックとポリモーフィズムを組み合わせることで、次のことができます。

public class Foo {} // declared elsewhere


public class Bar {} // declared elsewhere


public abstract class GenericParent<T> {
    private T self;

    public GenericParent(T self) {
        this.self = self;
    }

    protected T getSelf() {
        return self;
    }

    public abstract GenericChild<T> getChild();
}


public class FooChild extends GenericChild<Foo> {
    public FooChild(Foo foo) {
        super(foo);
    }
}


public class BarChild extends GenericChild<Bar> {
    public BarChild(Bar bar) {
        super(bar);
    }
}


public class FooParent extends GenericParent<Foo> {

    public FooParent(Foo foo) {
        super(foo);
    }

    public FooParent() {
        this(new Foo()); 
    }

    @Override
    public GenericChild<Foo> getChild() {
        return new FooChild(getSelf());
    }
}


public class BarParent extends GenericParent<Bar> {

    public BarParent(Bar bar) {
        super(bar);
    }

    public BarParent() {
        this(new Bar());
    }

    @Override
    public GenericChild<Bar> getChild() {
        return new BarChild(getSelf());
    }
}

また、メイン メソッドを少し変更する必要があります。

public static void main(String args[]) {
    GenericParent<?> parent;

    // Only the initialization of the parent variable needs specialized code
    switch(args[0]) {
        case "foo":
            parent = new FooParent();
            break;

        case "bar":
            parent = new BarParent();
            break;
    }

    parent.getChild().print();
}
于 2014-05-27T18:08:02.473 に答える
0

あなたの親はラッパーのようで、ラッパーはコンテナなので、型パラメータの恩恵を受けることができるものかもしれません.

しかし、コンストラクターの署名以外に型パラメーターが表示されないため (そして、selfとは何ですか? 境界もヒントも何もありません...)、ジェネリック型を使用しても、ここでは何も購入できません。関心のあるメソッドが void を返し、空のパラメーター リストを宣言する場合、型パラメーターを導入しても意味がありません。

ガイダンスは次のとおりです。クラスのメソッドが型パラメーターを持つことでメリットが得られる場合、つまり、型パラメーターがメソッドの戻り値の型またはシグネチャで役立つ場合は、クラスをジェネリック化します。それ以外の場合は、現在持っているものに固執してください。

于 2014-05-27T17:39:34.540 に答える