TL;博士
尝试实现一个层次流畅的界面,这样我就可以组合节点子类,同时也可以独立于类,但是获取类型参数不在其绑定错误范围内.
细节
我正在尝试实现一个解决方案,以便我可以创建一些类似于以下内容的东西:
farm
.animal()
.cat()
.meow()
.findsHuman()
.saysHello()
.done()
.done()
.dog()
.bark()
.chacesCar()
.findsHuman()
.saysHello()
.done()
.done()
.done()
.human()
.saysHello()
.done();
Run Code Online (Sandbox Code Playgroud)
同时也能做到:
Human human = new Human()
.saysHello()
Run Code Online (Sandbox Code Playgroud)
我已经接近使用各种策略,但未能获得所描述的灵活性.
我当前的尝试使用以下类:
abstract class Base<T extends Base<T>>{
private T parent;
Base(){
}
Base( T parent ){
this.parent = parent;
}
public T done() throws NullPointerException{
if ( parent != null ){
return (T) parent;
}
throw new NullPointerException();
}
}
class Farm<T extends Base<T>> extends Base{
private Animal<Farm<T>> …Run Code Online (Sandbox Code Playgroud) 这是我的第一个问题,我希望它对读者和我自己都足够有用!在过去的两天里,我用Google搜索并躲过了这个世界.
我有抽象的模型和存储类,从中派生出具体的模型和存储类:
abstract class Food {}
abstract class FoodStorage<T extends Food> {
abstract void setFood(T food);
}
class Apple extends Food {}
class Basket extends FoodStorage<Apple> {
@Override
void setFood(Apple apple) {
// Save that apple to the basket
}
}
Run Code Online (Sandbox Code Playgroud)
没问题.现在,我希望能够save()直接在一个Apple实例上调用它,将其持久化Basket(无需担心篮子),并在抽象类中实现.我发现的最好的是:
abstract class Food<T extends Food<T,S>,
S extends FoodStorage<T,S>> {
abstract S getStorage();
void save() {
getStorage().setFood((T)this); // <---- Unchecked cast warning
}
}
abstract class FoodStorage<T extends Food<T,S>, S extends FoodStorage<T,S>> { …Run Code Online (Sandbox Code Playgroud) 所以,我正在尝试这样的父/子类关系:
class ParentClass<C, T> where C : ChildClass<T>
{
public void AddChild(C child)
{
child.SetParent(this); //Argument 1: cannot convert from 'ParentClass<C,T>' to 'ParentClass<ChildClass<T>,T>'
}
}
class ChildClass<T>
{
ParentClass<ChildClass<T>, T> myParent;
public void SetParent(ParentClass<ChildClass<T>, T> parent)
{
myParent = parent;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这是一个编译错误.所以,我的第二个想法是SetParent用a 声明方法where.但问题是我不知道什么类型声明myParent(我知道类型,我只是不知道如何声明它.)
class ParentClass<C, T> where C : ChildClass<T>
{
public void AddChild(C child)
{
child.SetParent(this);
}
}
class ChildClass<T>
{
var myParent; //What should I declare this as?
public void SetParent<K>(ParentClass<K,T> …Run Code Online (Sandbox Code Playgroud) 我试图在java中创建两个相互包含的类之间的泛型关系.这些对象基本上形成一个alernating层树.到目前为止,我发现最接近的SO问题是:泛型的Java泛型,它对我的问题很接近并且有些帮助,但仍然不同,我想要额外的指导.这是情况,或者更确切地说,我希望它是什么:
abstract class Group<I extends Item<Group<I>>>{
private List<I> items;
public List<I> getItems(){...}
public void setItems(List<I> items){...}
}
abstract class Item<G extends Group<Item<G>>>{
private List<G> subGroups;
public List<G> getSubGroups(){...}
public void setSubGroups(List<G> subGroups){...}
}
Run Code Online (Sandbox Code Playgroud)
除了吸气剂和制定者之外,该类的某些方面使它们彼此明显不同,但包含应该遵循这样的方式.这背后的原因是我想强制执行,如果我有实现类,他们必须表现如下:
class AGroup extends Group<AItem>{...} //works
class AItem extends Item<AGroup>{...} //works
class BGroup extends Group<BItem>{...} //works
class BItem extends Item<BGroup>{...} //works
class MixedGroup extends Group<AItem>{...} //fails since AItem does
//not extend Item<MixedGroup>
Run Code Online (Sandbox Code Playgroud)
到目前为止,编译器很好用
abstract class Group<I extends Item<Group<I>>>{
private List<I> items;
public List<I> getItems(){...}
public …Run Code Online (Sandbox Code Playgroud) 实现的类Comparable<T>通常为自己实现它,例如
class MyInteger implements Comparable<MyInteger> { ... }
class MyString implements Comparable<MyString> { ... }
Run Code Online (Sandbox Code Playgroud)
但是没有什么可以阻止你为不同的类型实现它:
class MyString implements Comparable<MyInteger> { ... }
Run Code Online (Sandbox Code Playgroud)
这将允许您比较a MyString到a MyInteger.
正如Javadoc中所描述的那样,Comparable旨在模拟自然排序,这是一个总顺序,因此为了能够具有反对称性,参数的类型compareTo应该与该方法的类型相同.定义.
但实施有任何实际用途(滥用)class SomeType implements Comparable<OtherType>吗?
更新:Joni和我提供的答案提供了Comparable<Supertype>隐式实现的实际示例,即您的类可传递地实现该接口的位置.知道是否有人有明确使用它的例子会很有趣.
java中是否有一种编写通用接口的方法,以更方便的方式指出这种接口的实现者?
例如我写的界面:
public interface Updatable<T> {
void updateData(T t);
}
Run Code Online (Sandbox Code Playgroud)
我想指出只有实现者的实例可以在updateData(T t)方法中传递.
所以,我必须写这样的东西:
public class Office implements Updatable<Office> {
@Override
public void updateData(Office office) {
//To change body of implemented methods use File | Settings | File Templates.
}
...
...
...
}
Run Code Online (Sandbox Code Playgroud)
但似乎有点难看.你有更好的变种吗?
第二次尝试这个问题(初始代码不足以突出问题)
这是不编译的代码:
interface Player<R, G extends Game>
{
R takeTurn(G game);
}
interface Game<P extends Player>
{
void play(P player);
}
abstract class AbstractGame<R, P extends Player>
implements Game<P>
{
public final void play(final P player)
{
final R value;
value = player.takeTurn(this);
turnTaken(value);
}
protected abstract void turnTaken(R value);
}
public class XPlayer
implements Player<Integer, XGame>
{
@Override
public Integer takeTurn(final XGame game)
{
return (42);
}
}
public class XGame<P extends Player<Integer, XGame>>
extends AbstractGame<Integer, XPlayer> …Run Code Online (Sandbox Code Playgroud) 我正在开发一个流畅的API,并尝试利用Java的通用方法来提供一个优雅的API来处理我的用户的类型转换.由于类型擦除,我遇到了一些麻烦.
这是我的界面的简化版本,显示了我遇到的问题:
interface Query<T extends Query<T>> {
T execute();
Query<T> appendClause();
}
interface A<T extends A> extends Query<T> { }
class AImpl implements A<A> {
A execute() { ... }
Query<A> appendClause() { ... }
}
Run Code Online (Sandbox Code Playgroud)
我收到了错误AImpl.appendClause().编译器说它A不在其范围内,应该扩展Query.据我所知,我的声明,AImpl实现A<A>该方法A 不延长Query<A>.
在这里得到另一个答案后,我尝试通过更改AImpl为:分解任何潜在的无法解析的递归:
class AImpl implements A<AImpl> {
AImpl execute() { ... }
Query<AImpl> appendClause() { ... }
}
Run Code Online (Sandbox Code Playgroud)
现在我收到一个错误编译A,说"类型参数T不在其范围内".
有人对如何处理这个问题有任何建议吗?Java的泛型让我很头疼.
编辑
我把A的定义改为了
interface A<T extends A<T>> extends …Run Code Online (Sandbox Code Playgroud) 这个SO讨论提出了以下习语:
public interface IComparable<T extends IComparable<T>> {
int compare(T t);
}
Run Code Online (Sandbox Code Playgroud)
然后允许:
public class Foo implements IComparable<Foo> {
public int compare(Foo foo) {
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这个习惯用法不仅仅包括以上代码,因为下面的代码也可以编译:
class A implements IComparable<A> {
public int compare(A a) {return 0;}
}
public class Foo implements IComparable<A> {
public int compare(A a) {
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
因此(除非我误解了一些东西)原始成语并没有真正购买任何东西,而不是那么戏剧化:
public interface IComparesWith<T> {
int compare(T t);
}
public class A implements IComparesWith<A> {
public int compare(A a) {...}
}
Run Code Online (Sandbox Code Playgroud)
那么,有没有办法实际声明一个接口,以便任何类声明实现它有一个方法来与它自己的类的对象进行比较,没有任何漏洞,如上所述?
我显然无法将上述内容发布为评论,因此我创建了一个新帖子.
有什么方法可以在编译时对参数强制使用子类类型吗?
类似this但不适合实例 - 对于类?
我有课程:
public abstract class Animal {
public abstract void follow(Animal a); // <-- how to declare it?
}
Run Code Online (Sandbox Code Playgroud)
但我希望子类永远不要使用基类Animal,而只使用它自己(派生类)作为参数:
public class Fish extends Animal {
@Override
public void follow(Fish f) { // error here, since it expects Animal
tagAlong(f);
}
private void tagAlong(Fish f) {
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
我希望 aFish仅使用类型的参数Fish,而不是Animal像另一个子类Parrot仅使用Parrot方法上的参数一样follow()。
我强烈希望在编译时强制执行此操作,但如果没有其他可能,则运行时是一个(不太理想的)选项。
generics ×9
java ×9
c# ×1
c#-4.0 ×1
casting ×1
inheritance ×1
interface ×1
parameters ×1
parent-child ×1
type-safety ×1