0

ビューに表示される「モデル」クラスのプロパティを開発者が定義しなければならない状況を作りたいです。

解決策として列挙を使用することを考えましたが、スーパークラス(インターフェース)で列挙を定義することはできないと思います。

私の説明がわかりにくかったらすみません。説明するのはちょっと難しいです。具体的なケースで説明してみます。

Animal.java

public interface Animal {
    public void eat();
}

バード.java

public class Bird implements Animal
{
    private String name;
    private int age;
    private Beak beak;
    private Wings wings;

    public Bird(String name, int age, Beak beak, Wings wings)
    {
        this.name = name;
        this.age = age;
        this.beak = beak;
        this.wings = organ;
    }

    //getter setter..

    @Override
    public void eat() {
        //eating
    }
}

Snake.java

public class Snake implements Animal
{
    private String name;
    private int age;
    private Fang fangs;

    public Snake(String name, int age, Fang fangs)
    {
        this.name = name;
        this.age = age;
        this.fangs = fangs;
    }

    //getter setter..

    @Override
    public void eat() {
        //eating
    }
}

Zoo.java

public class Zoo 
{
    private ArrayList<Bird> birds = new ArrayList<Bird>();
    private ArrayList<Snake> snakes = new ArrayList<Snake>();
    private ArrayList<Object?> birdsShownFeatures = new ArrayList<Object?>();
    private ArrayList<Object?> snakesShownFeatures = new ArrayList<Object?>();

    public Zoo()
    {
        birds.add(new Bird("Vulture", 2, new CrookedBeak(), new WideWing()));
        birds.add(new Bird("Whatever", 3, new WhateverBeak(), new WhateverWing()));
        birds.add(new Bird("Wut", 4, new WutBeak(), new WutWing()));

        snakes.add(new Snake("Cobra", 5, new TwinFang()));
        snakes.add(new Snake("Whatever", 5, new WhateverFang()));
        snakes.add(new Snake("Wut", 5, new WutFang()));

        birdsShownFeatures.add(new Object?("name"));
        birdsShownFeatures.add(new Object?("beak"));
        birdsShownFeatures.add(new Object?("wings"));

        snakesShownFeatures.add(new Object?("name"));
        snakesShownFeatures.add(new Object?("fangs"));
    }

    public void showOff()
    {
        for(Bird bird:birds)
        {
            for(Object? object:birdsShownFeatures)
            {
                System.out.println("Bird: "+bird.unknownFunction(object));
            }
        }

        for(Snake snake:snakes)
        {
            for(Object? object:snakesShownFeatures)
            {
                System.out.println("Snake: "+snake.unknownFunction(object));
            }
        }
    }
}

Animal (Object?) のサブクラスの属性を一般化する必要があります。そして、その属性を取得する関数 (unknownFunction) を定義できる必要があります。

言い換えれば、動物のサブクラスの特定のプロパティを簡単に定義し、それに応じて処理できるようにしたいと考えています。

完璧な (非現実的な?) 例:

public class Zoo {
    private ArrayList<Bird> birds = new ArrayList<Bird>();
    private ArrayList<Snake> snakes = new ArrayList<Snake>();
    private ArrayList<Object> birdsShownFeatures = new ArrayList<Object>();
    private ArrayList<Object> snakesShownFeatures = new ArrayList<Object>();

    public Zoo()
    {
        birds.add(new Bird("Vulture", 2, new CrookedBeak(), new WideWing()));
        birds.add(new Bird("Whatever", 3, new WhateverBeak(), new WhateverWing()));
        birds.add(new Bird("Wut", 4, new WutBeak(), new WutWing()));

        snakes.add(new Snake("Cobra", 5, new TwinFang()));
        snakes.add(new Snake("Whatever", 5, new WhateverFang()));
        snakes.add(new Snake("Wut", 5, new WutFang()));

        birdsShownFeatures.add(Bird.NAME);
        birdsShownFeatures.add(Bird.BEAK);
        birdsShownFeatures.add(Bird.WINGS);

        snakesShownFeatures.add(Snake.NAME);
        snakesShownFeatures.add(Snake.FANGS);
    }

    public void showOff()
    {
        for(Bird bird:birds)
        {
            for(Object object:birdsShownFeatures)
            {
                System.out.println("Bird: "+bird.get(object));
            }
        }

        for(Snake snake:snakes)
        {
            for(Object object:snakesShownFeatures)
            {
                System.out.println("Snake: "+snake.get(object));
            }
        }
    }
}

アニマルを実装するクラスを作成するたびに、開発者にインターフェイスを実装する特定の列挙を作成するように強制することはできないため、列挙型は機能しません。

ヘビと鳥の両方の属性を一般化できる必要があります。しかし、まだ定義されています。特定のインターフェイスを実装するためにすべての属性を作成することは、 a** で必要なすべてのクラス (ネイティブを含む) にインターフェイスを実装させるのが面倒になるため、選択ではありません。

混乱しすぎたらごめんなさい。この事件をどう説明したらいいのかわからない。

4

1 に答える 1

0

リフレクションとジェネリックを使用できます。あなたの問題に対するこの答えですが、それは悪い選択だと思います。

テーブルの例を使用して(コメントを参照)、行を返すメソッド(:の場合)でジェネリックTable<T>のようなものを使用します。最終的な開発者が別の種類の行を必要とする場合、彼はあなたを別のものにオーバーライドできます。別のオプションは、テーブルコンストラクターでa を受け入れることです ( google guava functionsを参照)getRow()Bird"Vulture", 2, "CrookedBeak", "WideWing"getRowFunction<T, Row>


クイック & ダーティ サンプル ジェネリックおよびリフレクション コード サンプル:

抽象的な動物

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

public abstract class AbstractAnimal<T extends Enum<T>> {
    private List<T> selectedFields = new ArrayList<T>();

    public AbstractAnimal(Class<T> clazz)
    {
        if (clazz != null) {
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if (Modifier.isStatic(field.getModifiers()) && 
                    Modifier.isPublic(field.getModifiers())) {
                    this.selectedFields.add(Enum.valueOf(clazz, field.getName()));
                }
            }
        }
    }

    public abstract void eat();

    public List<T> getSelectedFields()
    {
        return this.selectedFields;
    }

    public Object get(T name)
    {
        if (name == null) {
            return null; 
        }

        try {
            final Class<?> clazz = this.getClass();
            final Field declaredField = clazz.getDeclaredField(name.name().toLowerCase());
            if (declaredField != null) {
                declaredField.setAccessible(true);
                return declaredField.get(this);
            }
        } catch (IllegalAccessException ex) {
            // ignore
        } catch (NoSuchFieldException e) {
            // ignore
        } catch (SecurityException e) {
            // ignore
        }
        return null;
    }
}

public class Bird extends AbstractAnimal<Bird.Fields> {

    public static enum Fields {
        NAME, AGE, BEAK, WINGS
    }

    private String name;

    private int age;

    private String beak;

    private String wings;

    public Bird(String name, int age, String beak, String wings)
    {
        super(Fields.class);
        this.name = name;
        this.age = age;
        this.beak = beak;
        this.wings = wings;
    }

    // getter setter..

    @Override
    public void eat()
    {
        // eating
    }
}

動物園

package com.foo;

import java.util.ArrayList;

public class Zoo {
    private ArrayList<Bird> birds = new ArrayList<Bird>();

    public Zoo()
    {
        birds.add(this.buildBird("Vulture", 2, "CrookedBeak", "WideWing"));
        birds.add(this.buildBird("Whatever", 3, "WhateverBeak", "WhateverWing"));
        birds.add(this.buildBird("Wut", 4, "WutBeak", "WutWing"));
    }

    public void showOff()
    {
        for(Bird bird:birds)
        {
            for (final Bird.Fields selectedField : bird.getSelectedFields()) {
                System.out.println("bird: " + bird.get(selectedField));
            }
        }
    }

    private Bird buildBird(String name, int age, String beak, String wings) 
    {
        Bird result = new Bird(name, age, beak, wings);
        result.getSelectedFields().remove(Bird.Fields.AGE);
        return result;
    }

    public static void main(final String[] args) {
        Zoo z = new Zoo();
        z.showOff();
    }
}

出力

bird: Vulture
bird: CrookedBeak
bird: WideWing
bird: Whatever
bird: WhateverBeak
bird: WhateverWing
bird: Wut
bird: WutBeak
bird: WutWing
于 2012-11-08T06:47:12.423 に答える