Java 如何定义或引用视图中要使用的模型类的属性
我想让开发人员定义视图中显示的“模型”类的属性 我曾想过使用枚举作为解决方案,但我认为不可能在超类(接口)中定义枚举 如果我的描述不清楚,我很抱歉。这有点难以解释。我会试着用一个具体的案例来解释 Animal.javaJava 如何定义或引用视图中要使用的模型类的属性,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;
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