为什么这个继承不起作用?

时间:2010-11-12 19:09:18

标签: c# inheritance

我有一个派生自TcpClient的类,例如

class ZClient : TcpClient
{
    public byte[] Buffer { get; set; }
    public Queue<byte[]> Queue {get; set;}
}

创建TcpClient的方法

...

TcpListener listener = ar.AsyncState as TcpListener;
ZClient client = listener.EndAcceptTcpClient(ar) as ZClient;

当我将通常返回TcpClient的listener.EndAcceptTcpClient(ar)转换为ZClient时,对象'client'为null。我试图做的是非法的吗?

更新:是否可以将ZClient基类的属性设置为等于通过构造函数传入的TcpClient,以避免必须有一个额外的属性来引用TcpClient的? e.g。

public ZClient(TcpClient client)
{
   base = client;  // I'm aware this doesn't work.
}

6 个答案:

答案 0 :(得分:6)

因为它倒退了。 TcpClient不包含Buffer或Queue,因为它不是ZClient。苹果是水果,但不是所有水果都是苹果。

您需要某种显式转换。您可以提供一个接受TcpClient的ZClient构造函数,或者在TcpClient上提供返回ZClient的扩展方法。这些中的任何一个都可能需要使ZClient成为TcpClient的包装类,而不是ZClient的子类。

答案 1 :(得分:4)

所有ZClient都是TcpCplient,但并非所有TcpClient都是ZClient s * TcpClient返回的TcpListener.EndAcceptTcpClientTcpClient,不能用作ZClient。您可以包装生成的TcpClient。我建议使用

形式的构造函数
private readonly TcpClient;
public ZClient(TcpClient tcpClient) {
    this.tcpClient = tcpClient;
}

* :也许一个不同的例子会有所帮助

class Animal { }
class Cat {
    public int NumberOfLives { get; private set; }
    public Cat() { NumberOfLives = 9; }
}

您是否能够(使用as)转换由Animal返回Cat的方法返回的任何对象?并非所有Animal都有脚,就像并非所有TcpClient都有一个名为byte[]的{​​{1}}或一个名为Buffer的{​​{1}}。因此,您无法将通用Queue<byte[]>视为Queue,就像您无法将通用TcpClient视为ZClient一样。

答案 2 :(得分:1)

你可能想要一个“有一个”而不是“是一个”TcpClient和ZClient之间的关系

class ZClient
{
    public ZClient(TcpClient client) 
    {
        this.client = client;
    }
    public TcpClient client {get; set;}
    public byte[] Buffer { get; set; }
    public Queue<byte[]> Queue {get; set;}
}

然后您可以将调用委托给底层TcpClient

答案 3 :(得分:0)

  

我试图做的是非法的吗?

是。 TcpListener怎么能知道如何提出ZClient?如果有,那么BufferQueue属性会做什么?

答案 4 :(得分:0)

listener.EndAcceptTcpClient(ar)正在给你TcpClient。您无法取TcpClient并假装它是ZClient。这不是继承的工作方式。

简而言之:

  • 根据定义,所有ZClient都是TcpClient
  • 并非所有TcpClient都是ZClient s。

例如,马是动物。并非所有动物都是马。

答案 5 :(得分:0)

如果从侦听器获取TcpClient,则侦听器将像往常一样返回TcpClient。你永远不会新兴ZClient。 TcpListener对您的新类一无所知,因此无法创建它。如果您只想拥有一个为TcpClient添加功能的对象,您可能只想使用组合而不是继承。简单地有一个ZClient,它通过在内部存储一个TcpClient来包装它,并添加你想要的任何功能。