我正在研究一个问题,其中不同的动物类型从Animal界面实现相同的talk()方法
如果你看一下getAnimal()
方法,你可以看到,当一种新的动物被添加到程序中时,该方法的内部也必须改变。
我想通过继承Animal来添加新动物而不改变现有类中的任何内容
例如,添加动物“狗”,标准=“忠诚”;谈= “汪汪”。
你能告诉我,它怎么可能?以下是我的代码:
interface Animal {
public void talk();
}
class Lion implements Animal {
@Override
public void talk() {
System.out.println("ROARRRRR");
}
}
class Mouse implements Animal {
@Override
public void talk() {
System.out.println("SQUEEEEEAK");
}
}
class Bison implements Animal {
@Override
public void talk() {
System.out.println("BELLOWWWWW");
}
}
class AnimalType {
public static Animal getAnimal(String criteria) {
// I refactor this method
if (criteria.equals("small")) {
return new Mouse();
} else if (criteria.equals("big")) {
return new Bison();
} else if (criteria.equals("lazy")) {
return new Lion();
}
return null;
}
}
public class AnimalExamples {
public static void main(String[] args) {
AnimalType.getAnimal("small").talk();
AnimalType.getAnimal("big").talk();
AnimalType.getAnimal("lazy").talk();
// how to add an animal "Dog" here, criteria="loyal"; talk="woof"
AnimalType.getAnimal("loyal").talk();
try {
AnimalType.getAnimal("small").talk();
} catch (Exception ex) {
System.out.println("Animal does not exists");
}
}
}
我在谷歌搜索,了解它可以通过反思来完成。但不知道如何。如果可能的话,你能帮我解决这个问题吗?提前谢谢!
答案 0 :(得分:3)
您知道运行时类生成非常复杂,并且不适合初学者使用该语言。这将是一个使用地图和匿名类的绝佳方案。
Html.Kendo().TreeView()
.Name("TreeViewTemplateBiding")
.TemplateId("TreeViewTemplate")
.BindTo((IEnumerable<OrgChart.Models.NodeViewModel>)ViewBag.Tree, (Kendo.Mvc.UI.Fluent.NavigationBindingFactory<TreeViewItem> mappings) =>
{
mappings.For<OrgChart.Models.NodeViewModel>(binding => binding.ItemDataBound((item, node) =>
{
item.Id = node.Id;
item.Text = node.Title;
//item.Expanded = node.Expanded;
})
.Children(node => node.Children));
})
)
如果您确实坚持真正的运行时类生成,或者您对它的工作原理感到好奇,请查看ByteBuddy。
答案 1 :(得分:2)
老问题,但这里是如何创建类...对我来说,简单的方法是使用Javassist。 我在这里创建了一个小例子:http://hrabosch.com/2018/04/08/generate-class-during-runtime-with-javassist/
但这是重点:
public static Class generateClass(String className, String methodName, String methodBody)
throws CannotCompileException {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass(className);
StringBuffer method = new StringBuffer();
method.append("public void ")
.append(methodName)
.append("() {")
.append(methodBody)
.append(";}");
cc.addMethod(CtMethod.make(method.toString(), cc));
return cc.toClass();
}
所以我做了...通过Javassist我在ClassPool中创建了一个类。我还在这个类中添加了一个方法,并通过反射调用它。
希望它有所帮助。
请记住要在生成的类中使用的任何内容 不是导入,因此您必须使用完全限定名称。
答案 2 :(得分:0)
你必须定义狗类
class Dog implements Animal {
@Override
public void talk() {
System.out.println("woof");
}
}
并将if else添加到AnimalType
} else if ("loyal".equals(criteria)) {
return new Dog();
}
答案 3 :(得分:0)
Java不支持在运行时创建类。然而,有更好的方法来实现你想要的东西。我会提出两个。
首先,您可以创建一个AnimalType
类,其中包含有关物种的所有共享行为。然后,您可以使用Animal
类,将AnimalType
作为构造函数参数。
其次,您可以使用prototype设计模式。在这种情况下,Animal
类需要clone
方法从原型中创建新动物。然后,工厂类可以拥有原型列表,并使用您想要的任何逻辑来选择要克隆的正确原型。
如果您需要其他任何选项的更多详细信息或示例代码,请在下面进行评论。