Инкапсуляция и противоположность делегата - не должно ли это быть обязанностью программиста - PullRequest
0 голосов
/ 05 сентября 2010

1) Одна из причин использования инкапсуляции заключается в том, что, скрывая внутренние детали реализации, мы можем изменять эти детали, не нарушая существующий код - это имеет смысл

a) Но я не понимаю аргументаэта инкапсуляция должна использоваться для того, чтобы пользователи не могли перевести внутренние данные объекта в недопустимое или незавершенное состояние.

Если я напишу класс и продам его другим программистам (которые реализуют этот класс в своих собственных)приложения), не должны ли они нести ответственность за правильный доступ к этому объекту?В конце концов, если они не используют объект правильно, то только его приложения пострадают из-за этого.

Аналогия (плохая) того, что мне приходится реализовывать инкапсуляцию ради других программистов, не переводящих внутренние данные (случайно или преднамеренно) в незаметное состояние, будет продавать водонепроницаемые телевизоры на случай, если покупателирешили плавать со своими телевизорами.

2) С

http://blogs.msdn.com/b/ericlippert/archive/2007/10/19/covariance-and-contravariance-in-c-part-three-member-group-conversion-variance.aspx

void Foo(Giraffe g) {}
void Bar(Animal a) {}

Action<Mammal> action1 = Foo; // illegal 
Action<Mammal> action2 = Bar; // legal

Почему первое присвоение является незаконным?Потому что вызывающий action1 может передать Тигра, но Фу не может взять Тигра, только Жирафа!Второе назначение является законным, потому что Бар может взять любое животное. «

Я понимаю аргументацию автора о том, почему Action<Mammal> action1 не может быть в состоянии принять Foo().Но с другой стороны, не должно ли быть обязанностью программиста не передавать в делегат аргументы, которые не могут обрабатывать зарегистрированные методы?

Таким образом, если какой-то программист регистрирует метод Foo, то они также будут знать:

• не вызывать action1 делегата с чем-либо кроме, чем с Giraffe аргументом

• Не регистрировать методы с сигнатурой, отличной от Foo (кроме случаев, когда метод определяет в качестве своего параметра aтип, из которого Mammal происходит)

thanx

Ответы [ 5 ]

3 голосов
/ 05 сентября 2010

Вы действительно задали здесь два вопроса, которые лучше было бы разделить.

Похоже, вы действительно не заботитесь о безопасности типов или пытаетесь направить людей к успеху.

На второй вопрос легко ответить очень конкретно, хотя:

Я понимаю авторские рассуждения о том, почему Action<Mammal> action1 не должно быть в состоянии принять Foo(). Но с другой рука, не должно ли быть программистом ответственность не переходить в делегировать любые аргументы, которые зарегистрированы методы не справляются?

Какой программист? Тот, кто создает экземпляр Action<Mammal>, или тот, кто его вызывает? Это могут быть два очень разных программиста, работающие в совершенно разных библиотеках. Почему программист , использующий и Action<Mammal>, должен беспокоиться о том, что делегат может на самом деле не работать на любом Mammal? Все дело в безопасности типов заключается в том, чтобы гарантировать, что вещи будут работать должным образом ... что вы не можете создать делегата, который будет взрываться во время выполнения из-за несовпадения типов.

Если вы не заботитесь о безопасности типов во время компиляции, возможно, вам следует вместо этого попробовать динамически типизированный язык.

2 голосов
/ 05 сентября 2010

Я думаю, ваш код всегда должен быть безопасным для типов.Возьмем ваш пример: человек A пишет класс R и продает его человеку B. Человек A не может контролировать, что человек B делает с этим классом.B может распространить класс R на другой класс S и продать его другим людям.Нет никакого способа убедиться, что произведенный не типобезопасный класс A будет работать соответствующим образом для всех, кто использует Bs класса S.

1 голос
/ 06 сентября 2010

Полагаю, это лучше всего выражать в коде: так вот (суть в комментарии в последней части)

отказ от ответственности: код не компилируется и не должен быть в состоянии

public interface AnimalHandler
{
   Action<Mammal> Feed{get;}
}


public class CreatedInFarAwayFromYou : AnimalHandler
{
  private void Foo(Giraffe g) {}
  public Action<Mammal> Feed
  {
     return Foo;
  }
}

public class MadeByYou
{

  private IEnumerable<Tiger> tigers;
  AnimalHandler handler;
  public void FeedAll()
  {
    foreach(var animal in tigers)
    {
       //You are by your reasoning at fault here. Not the dev that made CreatedInFarAwayFromYou 
       Feed(animal); 
    }
  }
}
1 голос
/ 05 сентября 2010

Аналогия с вашим телевизором подразумевает, что вам необходимо предвидеть все возможные сценарии, в которых используется ваш код, что невозможно. Вместо этого думайте о том, что вы делаете, чтобы сделать ваши намерения очевидными. Вам известны эти подробности об использовании объекта, так почему бы не инкапсулировать их вместо того, чтобы возлагать ответственность на потребителя?

Другая аналогия состоит в том, что у вас не может быть двери в дверях, и вы заявляете, что в мире лежит ответственность не входить внутрь; это не изменит силу открытой двери, чтобы вызвать любопытство в людях. Дверь означает «вам не разрешено входить в этот дом», когда люди не узнают, войдя внутрь во время выполнения, и вы выбросите AccessDeniedException. Намерение двери совершенно очевидно.

1 голос
/ 05 сентября 2010

Одним из преимуществ хорошей инкапсуляции является «принуждение» пользователя класса использовать его надлежащим образом, а не каким-либо другим возможным способом.Таким образом, пользователь меньше расстраивается из-за кода, который он должен (повторно) использовать.Производительность увеличивается (меньше времени тратится на выяснение причин взлома кода, особенно если исходный код недоступен) и т. Д.

Если мне нужно у кого-то купить библиотеку, и я должен быть очень осторожнымКак бы я ни использовал его на каждом этапе, я бы посчитал, что потратил впустую деньги.

(Я исключил темы дизайна библиотеки, стабильность, удобство обслуживания и расширяемость. Я смертелен, и время, чтобы покрыть эти аспекты ограничено:) ...)

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