简体   繁体   English

在接口扩展中指定泛型

[英]Specify Generics in interface extends

Should I specify the concrete type for generic types when extending an interface with another interface? 在使用另一个接口扩展接口时,是否应该指定泛型类型的具体类型?

What I mean is, if I have an interface: 我的意思是,如果我有一个界面:

public interface Repo<T>{
      Collection<T> search(String params);
      T get(String id);
}

and then a whole bunch specific Repositories, like ClientRepo , CustomerRepo , etc... is it reasonable to specify the type T when extending this interface, eg: 然后是一堆特定的存储库,如ClientRepoCustomerRepo等......在扩展此接口时指定类型T是合理的,例如:

public interface ClientRepo extends Repo<Client>{
}
public interface CustomerRepo extends Repo<Customer>{
}

where Client and Customer are just some classes. 客户和客户只是某些类。

Did anyone have a similar problem? 有没有人有类似的问题? I mean I could do: 我的意思是我能做到:

public interface ClientRepo<T> extends Repo<T>{
}

Addendum : Perhaps I should make my intent for having specific Repos (eg ClientRepo) more clear. 附录 :也许我应该让我更清楚地了解具体的Repos(例如ClientRepo)。 There is another interface called RepoFactory that returns appropriate Repo to the client, eg: 还有另一个名为RepoFactory的接口, 它将适当的Repo返回给客户端,例如:

public interface RepoFactory{
      ClientRepo createClientRepo();
      CustomerRepo createCustomerRepo();
}

This factory is implemented by implementors which in turn, provide the appropriate implementations of the concrete Repos. 该工厂由实现者实现 ,实现者反过来提供具体Repos的适当实现。

In fact from the above you could say that the interface Repo<T> is not used by the client of the api. 事实上,从上面你可以说api的客户端没有使用接口Repo <T>

Confusing enough I hope!!! 我希望有足够的困惑! Sorry :( 对不起:(

Well it depends if your extending interface/class could be generic, too. 嗯,这取决于您的扩展接口/类是否也是通用的。 In your example I would assume that you want to do 在你的例子中,我会假设你想做

public interface ClientRepo extends Repo<Client>{
}

Because with 因为有

public interface ClientRepo<T> extends Repo<T>{
}

You could do things like 你可以做的事情

ClientRepo<Customer> 

which is probably not the desired behaviour. 这可能不是理想的行为。

I've found a lot more utility in doing 我发现在做的事情上有很多实用性

public interface SomeRepo<T> extends Repo<T>{
}

Than in extending interfaces via 比通过扩展接口

public interface ClientRepo extends Repo<Client>{
}
public interface CustomerRepo extends Repo<Customer>{
}

That said, I've done both in the past, and will likely wind up doing both in the future. 也就是说,我过去都做过这两件事,并且将来很可能会做到这两件事。 If you detect too much duplicate code in the latter solution, I'd do my best to replace it with the former solution. 如果在后一种解决方案中检测到过多的重复代码,我会尽力用以前的解决方案替换它。

If you want any practical issues, it seems that compilers have a harder time realizing that `public interface ClientRepo extends Repo' can be compatible with Repo. 如果你想要任何实际问题,似乎编译器很难意识到“公共接口ClientRepo扩展Repo”可以与Repo兼容。 It doesn't happen too often (but when it does it takes a number of attempts to get the generics interfacing right). 它不会经常发生(但是当它发生时需要多次尝试才能使泛型接口正确)。

The purpose of generic interfaces (and generics on the whole) is to have a single generic implementation. 通用接口(以及整体上的泛型)的目的是具有单个通用实现。 Ie, even though your interface might have multiple implementations, they should all handle every valid parameter class. 即,即使您的接口可能有多个实现,它们也应该处理每个有效的参数类。

If you remove the parameter in a subsequent layer of interfaces, it kind of defeats the idea of having a generic interface in the first place. 如果删除后续接口层中的参数,那么首先就会失去创建通用接口的想法。 After all, you could simply do: 毕竟,你可以简单地做:

 public interface Repo {
      Collection search(String params);
      Object get(String id);
 }

 public interface ClientRepo {
      Collection<Client> search(String params);
      Client get(String id);
 }

Of course if you have external code that supports parametrised operations on any Repo implementation, having a generic interface could still be useful. 当然,如果您的外部代码支持任何Repo实现的参数化操作,那么拥有通用接口仍然有用。 But you can also argue that these operations should be part of the Repo interface. 但您也可以争辩说这些操作应该是Repo界面的一部分。

All in all, it's workable and isn't hard to justify but it looks a bit awkward to me: just by looking at your example, it's difficult to figure out what your intent is, which is always a sign of warning. 总而言之,这是可行的并且不难证明,但对我来说看起来有点尴尬:仅仅通过查看你的例子,很难弄清楚你的意图是什么,这总是警告的标志。

You could define types properly 可以正确定义类型

interface BaseType { }
interface Client extends BaseType {}
Then, you could define 然后,你可以定义
 interface Repo<T extends BaseType> { Collection<T> search(String params); T get(String id); } interface ClientRepo extends Repo<Client> { } 
And with implementation 并实施
 ClientRepo c = new ClientRepo() { @Override public Collection<Client> search(String params) {// implementation here } @Override public Client get(String id) {// implementation here } }; 
obtain a stricter type checking. 获得更严格的类型检查。

Turns out the solution I was looking for was simply to throw out all my specialized interfaces: 事实证明我正在寻找的解决方案只是抛弃我所有的专用接口:

public interface RepoFactory{
    Repo<Client> createClientRepo();
    Repo<Customer> createCustomerRepo(); }

This way I get to both keep my static type-checking to enforce the api and also gain an additional flexibility for implementations of my Factory. 这样我就可以保持静态类型检查以强制执行api,并为我的Factory的实现获得额外的灵活性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM