Java 帮助创建泛型类以避免代码重复

Java 帮助创建泛型类以避免代码重复,java,generics,google-app-engine,dry,Java,Generics,Google App Engine,Dry,我有一个简单的问题,使用Appengine保持干燥 除作为参数发送的对象外,以下两个功能完全相同。实际上,我有15个这样的函数。我试图找到一种方法来创建一个超级类或泛型来实现这一点 public void deleteRecord(Person s) { PersistenceManager pm = PMF.get().getPersistenceManager(); try { Person p = pm.getObjectById(Person.class

我有一个简单的问题,使用Appengine保持干燥

除作为参数发送的对象外,以下两个功能完全相同。实际上,我有15个这样的函数。我试图找到一种方法来创建一个超级类或泛型来实现这一点

public void deleteRecord(Person s) {

    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
        Person p = pm.getObjectById(Person.class, s.getId());
        pm.deletePersistent(p);
    } finally {
        pm.close();
    }
}

不幸的是,我似乎不能使用泛型,因为泛型不支持t.class

有什么好的建议怎么做不带复印机

多谢各位。
Daniel

这不需要泛型;使用thing.getClass()

(您应该在那里添加一个null检查,以防传入的参数为null)


[注意:在我发布答案后,当我意识到这里不需要泛型时,我更改了答案…]

最简单的方法是将类型作为参数引入:

public <T> void deleteRecord(Class<T> type, T s) {
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
                T p = pm.getObjectById(type, s.getId());
                pm.deletePersistent(p);
        } finally {
                pm.close();
        }
}
public void deleteRecord(类类型,ts){
PersistenceManager pm=PMF.get().getPersistenceManager();
试一试{
tp=pm.getObjectById(类型,s.getId());
pm.1(p);
}最后{
pm.close();
}
}

如果您的人员、产品等只是简单的类,没有子类,那么您可以使用
getClass()
而不是像Scott建议的那样指定显式参数。

如果您在DAO中使用此参数,我倾向于用类初始化它。所以也许

public class DAO<T> {

  private Class klass

  public DAO(Class klass) {
    this.klass = klass;
  }

  public void deleteRecord(T record) {
    PersistenceManager pm = PMF.get().getPersistenceManager();     
    try {     
      T p = pm.getObjectById(this.klass, record.getId());     
      pm.deletePersistent(p);     
    } finally {     
      pm.close();     
    }
  }
}
公共类DAO{
二等舱
公共DAO(klass类){
this.klass=klass;
}
公共记录(T记录){
PersistenceManager pm=PMF.get().getPersistenceManager();
试试{
tp=pm.getObjectById(this.klass,record.getId());
pm.1(p);
}最后{
pm.close();
}
}
}

这可能不是最简单的做事方式,但我忍不住认为从长远来看这是最有意义的

创建一个接口

// This is a terrible name, I know
public interface Identifier {
    // Assumes ID was an int
    public int getId();
    // Maybe have setId, too
}
在每个类中,实现接口及其方法

public class Person implements Identifier {
    public int getId() {
        //Implementation details here
    }
}
最后,您的删除方法:

public void deleteRecord(Identifier s) {

    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
        Identifier p = pm.getObjectById(s.getClass(), s.getId());
        pm.deletePersistent(p);
    } finally {
        pm.close();
    }
}

注意:我还没有完全测试这个。。。具体地说,我还没有测试pm.deletePersistent(p)是否可以使用。

DRY是一个很好的原则。吻也是如此;-)

这将被称为,例如:

theObject.deleteRecord(Person.class, s.getId());
theObject.deleteRecord(Product.class, s.getId());

由于这是一个无效的方法,而且PersistenceManager似乎无法处理泛型类型,因此我建议避免使用泛型。如果适用,此方法还有一个额外的好处,即您不需要修改产品、人员等的类型层次结构


缺点是,如果从多个地方调用此方法,可能会有许多地方更改签名-但很容易让编译器知道需要多长时间。

您可以使用枚举来隐藏这一点:

class FetchableThing {}
class Person extends FetchableThing {}
class Organisation extends FetchableThing {}

enum DAO<T extends fetchableThing> {
    Person(Person.class), Organisation(Organisation.class);

    private Class<T> myClass;
    private DAO(Class<T> myClass) { this.myClass=myClass;}

    public delete(String id) {
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
            T p = (T) pm.getObjectById(myClass, id);
            pm.deletePersistent(p);
        } finally {
            pm.close();
        }
    }
}

DAO.Person.delete("1234");
DAO.Organsation.delete("1234");
class-FetchableThing{}
类Person扩展了FetchableThing{}
类组织扩展了FetchableThing{}
枚举道{
人(人.类)、组织(组织.类);
私有类myClass;
私有DAO(类myClass){this.myClass=myClass;}
公共删除(字符串id){
PersistenceManager pm=PMF.get().getPersistenceManager();
试一试{
tp=(T)pm.getObjectById(myClass,id);
pm.1(p);
}最后{
pm.close();
}
}
}
DAO.Person.delete(“1234”);
DAO.组织。删除(“1234”);

你不能修改你的方法来接受一个类而不是一个对象吗?这些方法需要在同一个类中,还是每个方法都像它自己的一个类中一样?除了object之外,它不提供getId方法,所以你需要声明一个东西,因为你需要一个具有getId()方法的公共超类(或接口)。或者传递s.getId的结果()将其作为参数引入方法中?thing的运行时类是否保证是持久性管理器所期望的类?它难道不是它的子类吗?例如,如果使用Hibernate持久化,则thing可能是一个延迟加载代理,它只实现持久性管理器所期望的类。我正在编写sa我的东西。@pstanton:实际上我是在看到Buhb的回复之前写的。但是,结果证明Grundlefleck可能有更好的主意。不,我个人更喜欢你/我们的方法。编译时安全性和继承的正确使用=好。你的意思是在你的示例中使用
Product.class
?你不是指参数
type
而不是?我想你不是想写
Product.class
而是想写
type
…对吗?你能不能用另一个方法来包装这个方法,这个方法只需要一个
s
参数?前提是type参数等于
s
的确切类。但是如果是这样的话,你根本不需要泛型类型唯一的问题是,您的代码并没有在编译时限制试图删除无效类型的人,例如object.deleteRecord(Integer.class,s.getId())将编译,但在运行时失败。即使这样,我可能也不会转向泛型,我最有可能使用枚举类型提供的编译时约束。因此,枚举将包含可以提供所需15个左右类的成员。您认为泛型比这更好吗?“PersistenceManager似乎不适用于泛型类型”我认为Apache(或Oracle)的任何代码都不会使用泛型。
public void deleteRecord(Class classOfProduct, Object id) {

    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
            Object p = pm.getObjectById(classOfProduct, id);
            pm.deletePersistent(p);
    } finally {
            pm.close();
    }
}
theObject.deleteRecord(Person.class, s.getId());
theObject.deleteRecord(Product.class, s.getId());
class FetchableThing {}
class Person extends FetchableThing {}
class Organisation extends FetchableThing {}

enum DAO<T extends fetchableThing> {
    Person(Person.class), Organisation(Organisation.class);

    private Class<T> myClass;
    private DAO(Class<T> myClass) { this.myClass=myClass;}

    public delete(String id) {
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
            T p = (T) pm.getObjectById(myClass, id);
            pm.deletePersistent(p);
        } finally {
            pm.close();
        }
    }
}

DAO.Person.delete("1234");
DAO.Organsation.delete("1234");