Java 如何定义或引用视图中要使用的模型类的属性

Java 如何定义或引用视图中要使用的模型类的属性,java,oop,model-view-controller,Java,Oop,Model View Controller,我想让开发人员定义视图中显示的“模型”类的属性 我曾想过使用枚举作为解决方案,但我认为不可能在超类(接口)中定义枚举 如果我的描述不清楚,我很抱歉。这有点难以解释。我会试着用一个具体的案例来解释 Animal.java public interface Animal { public void eat(); } java public class Bird implements Animal { private String name; private int age;

我想让开发人员定义视图中显示的“模型”类的属性

我曾想过使用枚举作为解决方案,但我认为不可能在超类(接口)中定义枚举

如果我的描述不清楚,我很抱歉。这有点难以解释。我会试着用一个具体的案例来解释

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));
            }
        }
    }
}
公共类动物园
{
private ArrayList birds=new ArrayList();
private ArrayList snakes=new ArrayList();
private ArrayList birdshownfeatures=new ArrayList();
私有ArrayList SnakeShownFeatures=new ArrayList();
公共动物园()
{
添加(新鸟(“秃鹫”,2,新弯嘴(),新宽翼());
添加(newbird(“Whatever”,3,newwhateverbeak(),newwhateverwing());
添加(newbird(“Wut”,4,newwutbeak(),newwutwing());
添加(新蛇(“眼镜蛇”,5,新双牙());
添加(newsnake(“Whatever”,5,newwhateverfang());
添加(新蛇(“Wut”,5,新WutFang());
添加(新对象?(“名称”);
添加(新对象?(“鸟嘴”);
添加(新对象?(“翅膀”);
添加(新对象?(“名称”);
添加(新对象?(“毒牙”);
}
公众虚张声势
{
用于(鸟:鸟)
{
用于(对象?对象:鸟鸣特征)
{
System.out.println(“Bird:+Bird.unknownFunction(object));
}
}
用于(蛇:蛇)
{
用于(对象?对象:SnakeShownFeatures)
{
System.out.println(“Snake:+Snake.unknownFunction(object));
}
}
}
}
我必须概括动物(对象?)子类的属性。我必须能够定义一个函数来检索该属性(unknownFunction)

换句话说,我希望能够很容易地定义动物亚类的某些属性,并且能够进行相应的处理

完美(不真实?)示例:

公共类动物园{
private ArrayList birds=new ArrayList();
private ArrayList snakes=new ArrayList();
private ArrayList birdshownfeatures=new ArrayList();
私有ArrayList SnakeShownFeatures=new ArrayList();
公共动物园()
{
添加(新鸟(“秃鹫”,2,新弯嘴(),新宽翼());
添加(newbird(“Whatever”,3,newwhateverbeak(),newwhateverwing());
添加(newbird(“Wut”,4,newwutbeak(),newwutwing());
添加(新蛇(“眼镜蛇”,5,新双牙());
添加(newsnake(“Whatever”,5,newwhateverfang());
添加(新蛇(“Wut”,5,新WutFang());
添加(Bird.NAME);
鸟嘴特征。添加(鸟嘴);
添加(Bird.WINGS);
snakeshownfeatures.add(Snake.NAME);
蛇显示特征。添加(蛇。毒牙);
}
公众虚张声势
{
用于(鸟:鸟)
{
用于(对象:BirdShownFeatures)
{
System.out.println(“Bird:+Bird.get(object));
}
}
用于(蛇:蛇)
{
用于(对象:SnakeShownFeatures)
{
System.out.println(“Snake:+Snake.get(object));
}
}
}
}
枚举无法工作,因为我无法强制开发人员每次创建实现Animal的类时,都执行实现接口的特定枚举

蛇和鸟的属性都必须能够被广义化。但仍有定义。让每个属性实现一个特定的接口不是一个选择,因为让所有需要的类(包括本地类)实现一个接口将是一件痛苦的事情


对不起,如果太让人困惑了。我不知道如何正确解释这个案例。

您可以使用反射和泛型。这是你问题的答案,但我认为这是一个错误的选择

使用您的表示例(请参阅注释),我将使用类似于通用的
表的
方法,并使用
getRow()
方法返回一行(对于
Bird
“Vulture”,2,“crokedbike”,“WideWing”
),如果最终开发人员需要不同类型的行,他可以将您的
getRow
重写为其他行。 另一个选项是接受表构造函数中的
函数
(请参阅)


Quick&dirty示例通用代码和反射代码示例:

抽象动物
看看Java的反射API和注释,我读了一些关于它们的文章。我发现我可以通过执行field f=class.getField(“fieldName”)来获取字段引用;您是否知道一种更简单的方法,让开发人员不必费劲地获取字段(getClass,getField(“FieldName”))。此外,“FieldName”字符串不受约束。所以很容易出现人为错误。返回字段的Class.FieldName将是最好的。如果可能的话。我应该对字段进行枚举还是什么?嗯,如果我想在Zoo类中指定shownAttribute使其成为动态的呢?我希望能够动态定义在showOff()中显示哪些字段。嗯,我想我误解了您的需要。你能澄清一下你所说的动态是什么意思吗?我是说大画面是什么?你看,在我的动物园课上。我通过将它们添加到ShownFeatures Arraylist中来选择shownAttributes。而您通过向每个子类中的属性添加注释来选择它们。这意味着在您的解决方案中,如果开发人员只能操作Z,那么开发人员不能为自己选择属性
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));
            }
        }
    }
}
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