2012-06-19 88 views
1

我是Java新手,已经陷入了一种情况,很明显我误解了它如何处理泛型,但是阅读教程和搜索stackoverflow并没有(至少目前为止)除此之外,我认为我滥用通配符。作为一个头脑,我有一个C++背景,所以它如何处理模板可能会着色我如何处理这个问题。Java泛型 - 通配符

使用有代表性的类

abstract class PacketHeader{ 
    // some stuff 
} 

class TypeOfPacketHeader extends PacketHeader{ 
    // extended stuff 
} 

abstract class Packet<T extends PacketHeader>{ 
    T mHeader; 
    // some methods treating T as a type of PacketHeader 
    // some abstract methods 
} 

class TypeOfPacket extends Packet<TypeOfPacketHeader>{ 
    static TypeOfPacket obtain { 
     return new TypeOfPacket(); 
    } 
    // overriden abstract functions that call specific TypeOfPacketHeader methods on mHeader 
} 

interface PacketParser<T extends Packet<? extends PacketHeader>>{ 
T obtainPacket(); 
     void parse(T packet); 
} 

class ImplementedPacketParser implements PacketParser<TypeOfPacket>{ 
    TypeOfPacket obtainPacket(){ 
     return TypeOfPacket.obtain(); 
    } 
    void parse(TypeOfPacket packet){ 
     // code that relies on TypeOfPacket specific functions 
    } 
} 

这似乎都可以正确的(或至少日食不是抱怨),问题似乎我的产业的基本结构引起的,当我试图利用这里的其中。我的第一次尝试是:

class User{ 
    PacketParser mParser; 

    User(PacketParser parser){ 
     mParser = parser; 
    } 

    void DoSomething(){ 
     Packet packet = mParser.obtainPacket(); 
     // do some stuff with the packet 
     mParser.parse(packet); 
    } 
} 

并导致原始类型的警告。所以,我想......

class User{ 
    PacketParser<? extends Packet<? extends PacketHeader>> mParser; 

    User(PacketParser<? extends Packet<? extends PacketHeader>> parser){ 
     mParser = parser; 
    } 

    void DoSomething(){ 
     Packet<? extends PacketHeader> packet = parser.obtainPacket(); 
     // do some stuff with the packet 
     mParser.parse(packet); 
    } 
} 

但是这将导致一个错误,

的方法解析(捕获#9的?扩展包)的类型PacketParser>不适用的参数(包)

在这一点上,我已经决定,我误解东西关于泛型是如何工作的,所以我已经转向了stackoverflow,希望指向我在哪里出错,也许指向我正确的方向。

+1

恕我直言,不要随意用泛型试图描述一切,因为这是一个混乱的道路。尽量保持它尽可能简单,它更有可能是有道理的。 ;) –

+0

对我来说,至少对于设计中这些转折点的体系结构来说,现在看来要容易得多,而不是试图仅为一种情况开发,然后在后来对它们进行鞋拔。 – Khanmots

回答

0

在你User代码,编译器不知道在mParser? extends Packet<? extends PacketHeader>是相同类型Packet<? extends PacketHeader> packet局部变量。

您需要绑定将通过使User一般被用于数据包的类型:

class User<T extends Packet<?>> { 
    PacketParser<T> mParser; 

    User(PacketParser<T> parser){ 
     mParser = parser; 
    } 

    void DoSomething(){ 
     T packet = parser.obtainPacket(); 
     // do some stuff with the packet 
     mParser.parse(packet); 
    } 
} 

// and then when instantiating your User, specify the packet type: 
new User<TypeOfPacket>(new ImplementedPacketParser()) 

现在编译器知道T的IT看到代表同一类型的Packet<?>,而每一次它看见? extends Packet<?>可能是Packet<?>的不同亚型。

编辑:一个额外注:“? extends PacketHeader”不需要在PacketParser接口声明,因为Packet类已经限制了其TPacketHeader及其亚型。

// ? is implicitly constrained to "extends PacketHeader" because of 
// the way Packet's generic is defined 
interface PacketParser<T extends Packet<?>> { 
+0

II认为我明白现在发生了什么,我感谢你指出了隐含的约束。希望这个包是从mParser获得的,编译器能够找出它,但也许这太希望了(我肯定不想编写能够做到的编译器.. ) – Khanmots

+0

好像现在已经全部实现并编译而没有错误或警告。必须在上面的图层做一些调整,但不是太糟糕。谢谢你的包! – Khanmots

+0

没问题,很高兴我能帮忙! – matts

0

我对你的代码做了一些改变。现在编译。试试用这个。

abstract class PacketHeader { 
    // some stuff 
    } 
    class TypeOfPacketHeader extends PacketHeader { 
     // extended stuff 
    } 

    abstract class Packet<T extends PacketHeader> { 
     T mHeader; 
     // some methods treating T as a type of PacketHeader 
     // some abstract methods 
    } 

    class TypeOfPacket extends Packet<TypeOfPacketHeader> { 
     static TypeOfPacket obtain() { 
      return new TypeOfPacket(); 
     } 
     // overriden abstract functions that call specific TypeOfPacketHeader 
     // methods on mHeader 
    } 

    interface PacketParser<T extends Packet<? extends PacketHeader>> { 
     T obtainPacket(); 

     void parse(T packet); 
    } 

    class ImplementedPacketParser implements PacketParser<TypeOfPacket> { 
     public TypeOfPacket obtainPacket() { 
      return TypeOfPacket().obtain(); 
     } 

     private TypeOfPacket TypeOfPacket() { 
      // TODO Auto-generated method stub 
      return null; 
     } 

     public void parse(TypeOfPacket packet) { 
      // code that relies on TypeOfPacket specific functions 
     } 
    } 

Your User Class。

class User{ 
    private PacketParser mParser; 

    User(PacketParser parser) { 
     mParser = parser; 
    } 

    void DoSomething() { 
     Packet packet = mParser.obtainPacket(); 
     // do some stuff with the packet 
     mParser.parse(packet); 
    } 
}