泛型,接口和继承问题 [英] Generics, Interfaces, and Inheritance question

查看:105
本文介绍了泛型,接口和继承问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下,我有一个类TypeX和一个类型为InY的TypeX。

公共类类型X

{

.... < br $>
}


公共类型类型

:typeX

{

....

}


我还有一个界面IX

公共接口IX

{

typeX GetThing();

void SetThing(typeX x);

}


并且实现IX的泛型类ABC被定义为如此

公共类ABC< T>

:IX

其中T:typeX < br $> b $ b $

公共T GetThing(){return val;}

public void SetThing(typeX x){val = x;}

}


为什么这段代码无效? ABC< Tdoes实现接口,因为$ T $必须是typeX(或从中派生出来)

解决方案

< blockquote> public T GetThing(){return val;}


如果你创建ABC< TypeYthen这个签名是


public TypeY GetThing() ;


与您的界面声明不符。你可以让你的

界面通用

IX< T>

{

T GetThing();

void SetThing(T x);

}


Pete

8月21日,1:40 * pm,Peter Morris < mrpmorri ... @ SPAMgmail.comwrote:


* * * public T GetThing(){return val;}



如果你创建ABC< TypeYthen这个签名是


public TypeY GetThing();


与您的接口声明不符。 *你可以使你的

界面通用


IX< T>

{

* * T GetThing();

* * void SetThing(T x);


}


Pete



但是typeY是一个typeX,所以它仍然符合

界面的合同。


2008年8月21日星期四13:48:41 -0700, - < on *************** @ gmail.comwrote:


8月21日,1:40?* pm,Peter Morris < mrpmorri ... @ SPAMgmail.comwrote:


?*?*?* public T GetThing(){return val; }


如果您创建ABC< TypeYthen此签名是

公共TypeY GetThing();

与您的界面不匹配宣言。 ?*你可以使你的
界面通用

IX< T>
?*?* T GetThing();
?*?* void SetThing(T x);

}

Pete



但是typeY是一个typeX,所以它仍然是履行

界面的合同。



该类型的对象可用于履行合同,但只有typeX

本身可以履行合同_作为返回类型_。由于返回类型的方法不是
变体,因此返回继承typeX

的类型的方法与typeX类型的方法完全相同,并且所以在编译时没有

的方式让编译器确保你的类方法

实际上实现了接口的合同。


您可以通过使接口通用来修复它,但在我看来,

只能将GetThing()方法的返回值更改为

正确类型:typeX。那是:


类ABC< T:IX其中T:typeX

{

T val;

public typeX GetThing(){return val; }

public void SetThing(typeX x){val = x; }

}


现在,所有这一切,你的SetThing()方法都有问题

声明。也就是说,即使你确实使用实际类型而不是类型参数声明了

方法,字段

" val"与x不相容在方法中你也应该得到一个

编译器错误。


这个错误实际上更糟,因为不能保证任何

对typeX对象的任意引用实际上是类型为T的对象。因此,你可以显式地转换x类型。为了匹配类型T,但是

那么你只需通过抛弃泛型提供的类型安全性来消除通用

类的重点。


基本上,考虑到你所拥有的界面,它根本不清楚

是否有任何意义来实现它泛类。

接口要求类允许使用继承typeX的任何

类型的对象进行设置,但是您的泛型类可以用于具体的

方式,实际类型更受限制(即更多派生的类型为
类型)。


所以,如果你还有继承typeX的typeZ但声明使用了

类ABC< Twith typeY,如果你能得到代码来编译你会有

尝试存储typeZ对象的可能性在一个变量

typeY中,这是不允许的。它会抛出一个运行时异常,

假设您编写代码以便首先编译它。


鉴于基本设计似乎被打破了,这可能是无关紧要的,

但是......我会理所当然地认为你有充分的理由说明为什么那个

模式不是''' ta属性而不是两个显式方法。 :)


Pete


Imagine I have a class TypeX and a class TypeY that inherts TypeX.
public class typeX
{
....
}

public class typeY
: typeX
{
....
}

I also have an interface IX
public interface IX
{
typeX GetThing();
void SetThing(typeX x);
}

And a generic class ABC that implements IX and is defined like so
public class ABC<T>
: IX
where T : typeX
{
T val;
public T GetThing(){return val;}
public void SetThing(typeX x){val = x;}
}

Why is this code not valid? ABC<Tdoes implement the interface, due
to the fact that T must be of typeX (or derived from it)

解决方案

public T GetThing(){return val;}

if you create ABC<TypeYthen this signature is

public TypeY GetThing();

which does not match your interface declaration. You could make your
interface generic
IX<T>
{
T GetThing();
void SetThing(T x);
}

Pete


On Aug 21, 1:40*pm, "Peter Morris" <mrpmorri...@SPAMgmail.comwrote:

* * * public T GetThing(){return val;}


if you create ABC<TypeYthen this signature is

public TypeY GetThing();

which does not match your interface declaration. *You could make your
interface generic

IX<T>
{
* * T GetThing();
* * void SetThing(T x);

}

Pete

But typeY is a typeX, so it still fulfills the contract of the
interface.


On Thu, 21 Aug 2008 13:48:41 -0700, -- <on***************@gmail.comwrote:

On Aug 21, 1:40?*pm, "Peter Morris" <mrpmorri...@SPAMgmail.comwrote:

?* ?* ?* public T GetThing(){return val;}


if you create ABC<TypeYthen this signature is

public TypeY GetThing();

which does not match your interface declaration. ?*You could make your
interface generic

IX<T>
{
?* ?* T GetThing();
?* ?* void SetThing(T x);

}

Pete


But typeY is a typeX, so it still fulfills the contract of the
interface.

An object of that type can be used to fulfill the contract, but only typeX
itself can fulfill the contract _as a return type_. Since methods aren''t
variant by return type, a method that returns a type that inherits typeX
is not the same as a method that the type typeX exactly, and so there''s no
way at compile time for the compiler to be sure that your class method
actually implements the interface''s contract.

You could fix it by making the interface generic, but it seems to me you
could just change the return value for the GetThing() method to be the
correct type: typeX. That is:

class ABC<T: IX where T : typeX
{
T val;
public typeX GetThing() { return val; }
public void SetThing(typeX x) { val = x; }
}

Now, all that said, you have a problem in your SetThing() method
declaration as well. That is, even though there you did declare the
method with the actual type rather than the type parameter, the field
"val" is incompatible with "x" in the method and you should be getting an
compiler error there too.

That error is actually worse, because there''s no guarantee that any
arbitrary reference to an object of typeX will in fact be an object of
type T. So, you could explicitly cast the "x" to match the type T, but
then you''d just wind up removing the whole point of having the generic
class by casting away the type safety that generics provide.

Basically, given the interface you''ve got, it''s not clear at all that it
makes any sense whatsoever to implement it with a generic class. The
interface requires that the class allow setting using an object of any
type that inherits typeX, but your generic class can be used in a concrete
way where the actual type is more restricted (i.e. is some more-derived
type).

So, if you also had typeZ that inherits typeX but declared a usage of
class ABC<Twith typeY, if you could get the code to compile you''d have
the possibility of trying to store an object of typeZ in a variable of
typeY, which would not be allowed. It''d throw a run-time exception,
assuming you wrote the code so that it compiled in the first place.

Given that the basic design seems to be broken, this may be irrelevant,
but...I''ll take as granted that you have a good reason for why that
pattern isn''t a property instead of two explicit methods. :)

Pete


这篇关于泛型,接口和继承问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆