#c# #oop
#c# #ООП
Вопрос:
Как заставить WebSocketClient
экземпляр класса использовать IWebSocketClient
интерфейс в его создании?
Например У меня нет ConnectAsync
метода, указанного в интерфейсе, и я ожидаю, что код не позволит мне его вызвать.
IWebSocketClient webSocketClient = new WebSocketClient(uri); await webSocketClient .ConnectAsync(CancellationToken.None) // ConnectAsync is missing which is expected behavior .ConfigureAwait(false);
var webSocketClient = new WebSocketClient(uri); await webSocketClient .ConnectAsync(CancellationToken.None) // it allows me to call it, which is not expected behavior .ConfigureAwait(false);
Отрывок
public interface IWebSocketClient : IDisposable { WebSocketState State { get; } } public class WebSocketClient : IWebSocketClient { public WebSocketClient(Uri uri) { } /// lt;inheritdoc /gt; public WebSocketState State =gt; _webSocket.State; public async Task ConnectAsync(CancellationToken cancellationToken) { ... } }
Комментарии:
1. Не предоставляйте общедоступный конструктор, а вместо этого используйте фабричный метод. (Если уж на то пошло, если вы не хотите, чтобы код вызывал общедоступную функцию, почему она является общедоступной? Должно ли оно существовать где-то еще?)
2. @AnthonyPegram, хорошая идея. Я также помню , что я мог бы сделать явную реализацию интерфейса
async Task IWebSocketClient.ConnectAsync(CancellationToken cancellationToken)
, которая побуждает людей использовать интерфейс.3. Да, явная реализация работает для этого метода, если он объявлен интерфейсом, но вы, по-видимому, намеренно исключили его из определения интерфейса. Но если вы хотите, чтобы этот метод на самом деле был виден только через интерфейс, то лучше всего использовать явный способ.
4. @AnthonyPegram, мне тоже нравится фабричный метод. Вы предлагаете
public static IWebSocketClient Create(Uri uri) =gt; new WebSocketClient(uri);
и сами сделать конструкторinternal
?5. Если конструктор является внутренним, то любой класс в сборке может вызывать его, поэтому, если вы собираетесь использовать этот класс в той же сборке (и не хотите прямого построения), он должен быть более ограниченным. Начните с private (это означает, что класс предоставляет свой собственный фабричный метод) и работайте дальше.
Ответ №1:
Создайте базовый абстрактный класс, а затем реализуйте интерфейс в виде абстрактных методов. Это заставит все подклассы реализовать эти методы.
Правка: Перечитывая ваш вопрос, я задаюсь вопросом, не неправильно ли я понял вашу проблему. Если вы хотите, чтобы у IWebSocketClient всегда был метод ConnectAsync, вы просто добавляете этот метод в интерфейс. Прямо сейчас интерфейс имеет только состояние, а не метод ConnectAsync.
Если в качестве альтернативы вы не хотите, чтобы какой-либо другой код мог вызывать ConnectAync, вам нужно сделать его закрытым.