Почему это наследство не работает? - PullRequest
1 голос
/ 12 ноября 2010

У меня есть класс, производный от 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;

.EndAcceptTcpClient (ar), который обычно возвращает TcpClient как ZClient.Что я пытаюсь сделать нелегальным?

Обновление : можно ли установить свойства базового класса ZClient равными TcpClient, которые передаются через конструктор, какчтобы избежать необходимости иметь дополнительное свойство для ссылки на TcpClient?например,

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

Ответы [ 6 ]

6 голосов
/ 12 ноября 2010

Потому что это задом наперед. TcpClient не содержит буфера или очереди, потому что это не ZClient. Яблоки - это фрукты, но не все фрукты - это яблоки.

Вам понадобится какое-то явное преобразование. Вы можете предоставить конструктор ZClient, который принимает TcpClient, или метод расширения для TcpClient, который возвращает ZClient. Любой из них, вероятно, потребует сделать ZClient классом-оберткой для TcpClient, а не потомком ZClient.

4 голосов
/ 12 ноября 2010

Все ZClient с TcpCplient с, но не все TcpClient с ZClient с *.TcpClient, возвращаемое TcpListener.EndAcceptTcpClient - это TcpClient, которое нельзя использовать как 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[] с именем Buffer или Queue<byte[]> с именем Queue.Следовательно, вы не можете думать о обобщенном TcpClient как о ZClient так же, как вы не можете думать о обобщенном Animal как о Cat.

1 голос
/ 12 ноября 2010

Вы, вероятно, хотите, чтобы между 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

0 голосов
/ 12 ноября 2010

Если вы получаете TcpClient от слушателя, то слушатель просто вернет вам TcpClient, как это всегда бывает.Вы никогда не обновляете ZClient.TcpListener ничего не знает о вашем новом классе, поэтому он не может его создать.Если вы просто хотите иметь объект, который добавляет функциональность к TcpClient, вы можете просто использовать композицию, а не наследование.Просто используйте ZClient, который оборачивает TcpClient, сохраняя его внутри, и добавляйте любые функции, которые вам нужны.

0 голосов
/ 12 ноября 2010

listener.EndAcceptTcpClient(ar) возвращается к вам TcpClient.Вы не можете взять TcpClient и сделать вид, что это ZClient.Это не то, как работает наследование.

Короче говоря:

  • Все ZClient s TcpClient s по определению.
  • Не все TcpClient sZClient с.

Например, лошадь - это животное.Не все животные - лошади.

0 голосов
/ 12 ноября 2010

Что я пытаюсь сделать незаконным?

Да.Как мог TcpListener знать, как придумать ZClient?Если это так, что будут делать свойства Buffer и Queue?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...