我想让开发人员必须定义要在视图中显示的“模型”类的属性。
我曾想过使用枚举作为解决方案,但我认为不可能在超类(接口)中定义枚举。
如果我的描述不清楚,我很抱歉。这有点难以解释。我会尝试用特定的案例来解释。
Animal.java
public interface Animal {
public void eat();
}
Bird.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));
}
}
}
}
枚举无法正常工作,因为我无法 FORCE 开发人员在每次创建实现Animal的类时都会进行实现接口的特定枚举。
蛇和鸟属性必须能够一般化。但仍然定义。使每个属性实现一个特定的接口都不是一个选择,因为在所有需要的类(包括本机)实现一个接口的过程中会很痛苦。
很抱歉,如果它太混乱了。我不知道如何正确解释这个案子。
答案 0 :(得分:0)
您可以使用反射和泛型。这是对你问题的回答,但我认为这是一个糟糕的选择。
使用您的表示例(请参阅注释)我会使用类似通用Table<T>
的方法,并使用getRow()
方法返回一行(对于Bird
:"Vulture", 2, "CrookedBeak", "WideWing"
),如果最终的开发者想要一个不同的行,他可以覆盖你的getRow
到别的东西。
另一种选择是在表构造函数中接受Function<T, Row>
(参见google guava functions)
快速&amp;脏样本泛型和反射代码示例:
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