我们假设我们有一个课程,其中包含以下方法:
public class Entry {
private String name;
public static Entry getOrCreate(String name) {
// ...
return new Entry(name);
}
}
这个类可以是子类(例如SubEntry
),以及" getOrCreate"不会改变。但是子类不应该返回类型为Entry
的新对象,而是返回相应子类的类型(例如return SubEntry(name)
)
如果不为getOrCreate
的每个子类重新实现方法Entry
,我怎样才能实现这一点?是否有这种技术的术语?
答案 0 :(得分:1)
子类化Entry
不会影响getOrCreate
方法,因为静态方法不是类实例的一部分;他们在逻辑上不属于任何阶级。
如果您将getOrCreate
移动到非静态Factory类中,则可以使用一些Generics魔术来确定返回的类型:
public class Entry {
private String name;
}
abstract class AbstractEntryFactory<T extends Entry>
public abstract T getOrCreate(String name);
}
public class EntryFactory extends AbstractEntryFactory<Entry>
@Override
public Entry getOrCreate(String name) {
// ...
return new Entry(name);
}
}
public class SubEntryFactory extends AbstractEntryFactory<SubEntry>
@Override
public SubEntry getOrCreate(String name) {
// ...
return new SubEntry(name);
}
}
实际上调用getOrCreate
看起来与您的代码看起来有所不同。而不是:
Entry myEntry = Entry.getOrCreate("my name");
它看起来像这样:
Entry myEntry = new EntryFactory().getOrCreate("my name");
或者这个:
SubEntry myEntry = new SubEntryFactory().getOrCreate("my name");
答案 1 :(得分:0)
假设您希望能够调用Entry.getOrCreate()
来创建一种SubEntry,则必须传递一些额外的信息。原因是getOrCreate()
方法不会继承SubEntry
方法,因为它是static
方法。因此,如果您想按照我提到的方式调用它,则必须传递要创建的类名。在下面的代码中,没有用于验证Class clazz
是Entry
还是子类型的检查,但这可以帮助您开始。
import java.lang.reflect.Constructor;
public class TestClass {
public static void main(String[] args) {
Entry entry = (Entry)Entry.getOrCreate("entry", Entry.class);
SubEntry subEntry = (SubEntry)SubEntry.getOrCreate("subEntry", SubEntry.class);
System.out.println("entry class: " + entry.getClass().getName());
System.out.println("subEntry class: " + subEntry.getClass().getName());
}
}
class Entry {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static Object getOrCreate(String name, Class clazz) {
// If a constructor is created that takes a String, such as "public Entry(String name)",
// then each sub class will need to implement that method. Instead I used a getter and
// setter for the name attribute.
try {
Entry entry = (Entry)clazz.newInstance();
entry.setName(name);
return entry;
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
class SubEntry extends Entry {
}
最终结果是这个输出:
entry class: Entry
subEntry class: SubEntry
答案 2 :(得分:0)
您提出两个问题:
第二个比第一个重要得多。
在我看来,您尝试实现的内容类似于克隆(link)或虚拟构造函数的概念。但是你希望这是一个静态方法,它提出了为什么这样的问题?由于静态方法与某个类相关联,而不是实例,因此您应该通过该类调用它,在这种情况下,您可以明确地调用new
。但是,在搜索“静态上下文中的反向类”时,我会说不可能完全按照你在问题中写的那样做。
如果将静态方法转换为普通方法,可以使用反射来完成:
class Entry {
private String name;
public Entry(String name) {
this.name = name;
}
public Entry() {
this.name = null;
}
public Entry getOrCreate(String name) {
try {
return getClass().getConstructor(String.class).newInstance(name);
} catch (Exception e) {
return new Entry(name);
}
}
}
class BetterEntry extends Entry {
public BetterEntry(String name) {
super(name);
}
public BetterEntry() {
super();
}
}
然后你将从一个实例调用该函数,如下所示:
Entry a = new Entry().getOrCreate("First");
Entry b = new BetterEntry().getOrCreate("Second");
Entry c = b.getOrCreate("Third");
a,b,c的动态类型是Entry,BetterEntry和BetterEntry。您可以省略默认构造函数,但我添加了它们以使调用getOrCreate
更像静态方法。
如果你真的希望这个方法是静态的,最简单的方法就是在每个子类中重新实现这个函数。