Как наследование Java используется для обеспечения выполнения требований программы? - PullRequest
1 голос
/ 22 июля 2010

Я смотрел в блоге о хорошем дизайне API текст ссылки

В одном из примеров разделов, озаглавленных «Изобретая сокет», он показал, как применять определенные правилаи обязательное условие для клиентского кода, который его использует.например.клиент должен вызвать bind (), прежде чем он сможет вызвать connect (), и он должен быть подключен, прежде чем ему разрешено отправлять () или получать () данные.

Я более знаком с C / C ++, поэтому яУ меня возникли проблемы с полным пониманием того, как дизайн класса обеспечивает соблюдение правил API.Как, например, как вы предотвращаете выполнение клиентским кодом вызовов в этот API с помощью чего-то вроде этого:

SocketConnected s = socket.bind(localaddress, 1000);

//client doesn't call the connect() method
//and just calls the send() method right away.

//this line should give compile-time error
//because only bind() was called but not connect()
s.send(/* some data goes here */);

Как и почему компилятор может отловить эту ошибку?Если я правильно понимаю наследование подкласса, то SocketConnected - это SocketBound, который - это Socket.Но если клиентский код может объявить объект SocketConnected, как вы можете применять правило, при котором bind () и connect () должны вызываться до того, как send () и receive () будут разрешены?

Спасибо

Ответы [ 2 ]

3 голосов
/ 22 июля 2010

Вы применяете правила, предоставляя только bind() в качестве создателя, и не используете публичный конструктор для SocketConnected. Нет другого способа создания SocketConnected, кроме как через API. Да, вы можете объявить объект этого класса, но вы не можете создать его самостоятельно; следовательно, вы не можете вызывать методы экземпляра, пока не будет вызван соответствующий создатель.

ДОБАВЛЕНО: Повторяйте ваш комментарий к bind().connect(): это всего лишь пример объединения, что-то вроде плавного интерфейса , но с ограничениями типов, контролирующими порядок вызовов. Подумай о том, что происходит. Первый bind() вызов создает экземпляр, на котором вы затем можете вызвать connect(). Последний пример кода, предоставленный разработчиком, является контраст : именно так все будет выглядеть с традиционной библиотекой сокетов в стиле Беркли, где s - это сокет, на котором оба 1016 * и connect() можно вызывать, в любом порядке, без жалоб компилятора.

ДОБАВЛЕНО: Шаблон повторного проектирования - я не думаю, что это было названо. Наверное, так и должно быть. Он поддерживает изменение критерия проектирования fail fast , поскольку происходит сбой еще на этапе компиляции.

2 голосов
/ 22 июля 2010

Дело в том, что он создает интерфейсы, которые определены только для возврата связанных сокетов. Вы получаете поставщика, который определен только для возврата связанных / подключенных сокетов.

если у вас есть экземпляр его SocketBound

 public interface SocketBound {
        SocketConnected connect(Address<?> address, int port);
    }

Вы можете получить только SocketConnected от него.

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