Generics Entity and EntityDTO similar methods

huangapple go评论58阅读模式
英文:

Generics Entity and EntityDTO similar methods

问题

有没有办法将 getEntityIdgetEntityDTOId 合并?

public class Entity {
	
	private Integer id;

	public Integer getId() {return id;}

}

public class EntityDTO {
	
	private Integer id;

	public Integer getId() {return id;}

}

public class EntityProcessing {
	
	public Integer getEntityId(Entity entity) {

		return entity.getId();

	}

	public Integer getEntityDTOId(EntityDTO entityDTO) {

		return entityDTO.getId();

	}

}

我已经了解了泛型,但不知道如何在这种情况下实现它。

英文:

Is there any way to unite getEntityId and getEntityDTOId?

public class Entity {
	
	private Integer id;

	public Integer getId() {return id;}

}

public class EntityDTO {
	
	private Integer id;

	public Integer getId() {return id;}

}

public class EntityProcessing {
	

	public Integer getEntityId(Entity entity) {

		return entity.getId();

	}

	public Integer getEntityDTOId(EntityDTO entityDTO) {

		return entityDTO.getId();

	}

}

I've read about Generics, but can't understand how to implement them in such a case.

答案1

得分: 3

你可以例如创建一个接口:

public interface WithId {
    Integer getId();
}

然后在实现它(你需要在希望在EntityProcessing.getId方法中使用的所有类中实现这个接口):

public class Entity implements WithId { // 添加implements ...

    private Integer id;

    @Override // 添加以标记它是接口中的方法
    public Integer getId() {return id;}

}

现在,你可以创建一个方法来从实现WithId接口的所有类中获取ID:

public Integer getId(WithId withId) {
    return withId.getId();
}

另一种选择是使用包含ID字段的抽象类。但这违反了里斯科夫替代原则(SOLID面向对象编程原则中的L)。还有一个限制,你在Java中只能扩展一个类,但可以实现多个接口。所以在我看来,最好像上面那样使用接口,但为了完整性,我也添加了这个解决方案。

public abstract class WithId {
    private Integer id;

    public Integer getId() {
        return id;
    }
}

然后扩展抽象类:

public class Entity extends WithId { // 在这种情况下添加extends ...

    // 你不需要在这里添加任何内容,
    // 因为字段和方法已经在基类中存在
}

使用方式与上面的第一种解决方案相同。

这个解决方案乍看之下似乎更好,因为你只需要在抽象类中编写方法一次,但你必须记住限制(你在Java中只能扩展一个类),因为如果你将来想要添加另一个常见字段,例如createdDate,你可以实现第二个接口,例如WithCreatedDate,但你不能扩展第二个类。

英文:

You can for example create some interface:

public interface WithId {
    Integer getId();
}

and implement it (you need to implement this interface in all the classes you want to use in the EntityProcessing.getId method):

public class Entity implements WithId { // add implements ...
    
    private Integer id;

    @Override // add to mark that it's method from the interface
    public Integer getId() {return id;}

}

And now you can create one method to get id from all the classes implementing WithId interface:

public Integer getId(WithId withId) {
    return withId.getId();
}

The other option is to use abstract class containing the id field. But it's against Liskov Substitution Principle (L from SOLID object oriented programming principles).

And there is a limitation, that you can extend only one class in java, but you can implement multiple interfaces. So in my opinion better use interface like above, but for completeness I added this solution as well.

public abstract class WithId {
    private Integer id;

    public Integer getId() {
        return id;
    }
}

and extend the abstract class:

public class Entity extend WithId { // in this case add extend ...

    // you don't need to add anything here,
    // because field and the method are already present in the base class
}

And usage is the same as in the first solution above.

This solution at the first glance seems to be better because you can write the method only once in the abstract class, but you have to remember the limitations (you can extend only one class in java), because if you want in the future add another common field like e.g. createdDate - you can implement second interface e.g. WithCreatedDate, but you cannot extend second class

答案2

得分: 0

你提供的示例实际上并不需要使用泛型,但看起来你正在学习关于泛型:

public class Test {
    public static void main(String[] args) {
        Entity entity = new Entity();
        EntityDTO entityDTO = new EntityDTO();

        EntityProcessing<Base> a = new EntityProcessing<>();
        System.out.println(a.getEntityId(entity));
        System.out.println(a.getEntityId(entityDTO));

        System.out.println(EntityProcessing.getId(entity));
        System.out.println(EntityProcessing.getId(entityDTO));
    }
}

interface Base {
    public Integer getId();
}

class Entity implements Base {
    private Integer id = 1;
    public Integer getId() {return id;}
}

class EntityDTO implements Base {
    private Integer id = 2;
    public Integer getId() {return id;}
}

// T 必须是 Base 的子类型,否则,在泛型擦除之后,T 类型将没有 getId 方法
class EntityProcessing<T extends Base> {
    public Integer getEntityId(T entity) {
        return entity.getId();
    }

    // 泛型方法
    // T 必须是 Base 的子类型,否则,在泛型擦除之后,T 类型将没有 getId 方法
    // 请注意,泛型方法中的 <T> 与泛型类的生命周期中的 <T> 之间没有关系。你完全可以将此处的 T 替换为 R 或任何其他字符。
    // public static <F extends Base> Integer getId(F entity)
    // public static <ABC extends Base> Integer getId(ABC entity)
    // .....
    public static <T extends Base> Integer getId(T entity) {
        return entity.getId();
    }
}
英文:

The example you provided, doesn't actually need to use generics, but it looks like you're learning about generics:

public class Test {
public static void main(String[] args) {
Entity entity = new Entity();
EntityDTO entityDTO = new EntityDTO();
EntityProcessing&lt;Base&gt; a = new EntityProcessing&lt;&gt;();
System.out.println(a.getEntityId(entity));
System.out.println(a.getEntityId(entityDTO));
System.out.println(EntityProcessing.getId(entity));
System.out.println(EntityProcessing.getId(entityDTO));
}
}
interface Base {
public Integer getId();
}
class Entity implements Base {
private Integer id = 1;
public Integer getId() {return id;}
}
class EntityDTO implements Base {
private Integer id = 2;
public Integer getId() {return id;}
}
// T must be a subtype of Base, otherwise, after generic erasure, the T type does not have a getId method
class EntityProcessing&lt;T extends Base&gt; {
public Integer getEntityId(T entity) {
return entity.getId();
}
// Generics Method
// T must be a subtype of Base, otherwise, after generic erasure, the T type does not have a getId method
// Note that there is no relationship between the &lt;T&gt; in the generic method and the &lt;T&gt; in the life of the generic class.You can completely replace the T here with an R, or any other char
// public static &lt;F extends Base&gt; Integer getId(F entity)
// public static &lt;ABC extends Base&gt; Integer getId(ABC entity)
// .....
public static &lt;T extends Base&gt; Integer getId(T entity) {
return entity.getId();
}
}

huangapple
  • 本文由 发表于 2023年2月16日 16:37:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/75469635.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定