Вопрос

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

В C # договор может быть определен с использованием интерфейса. Класс, который реализует интерфейс, должен выполнить условия в договоре, предоставляя реализацию для каждого метода и имущества (и, возможно, другие вещи). Отдельный класс, который реализует интерфейс, может делать все необходимое в объеме методов, определенных договором, до тех пор, пока он принимает одинаковые типы аргументов и возвращает тот же тип результата.

Есть ли способ обеспечить такого рода вещи в Руби?

Спасибо

Простой пример того, что я имею в виду в C #:

interface IConsole
{
    int MaxControllers {get;}
    void PlayGame(IGame game);
}

class Xbox360 : IConsole
{
   public int MaxControllers
   {
      get { return 4; }
   }

   public void PlayGame(IGame game)
   {
       InsertDisc(game);
       NavigateToMenuItem();
       Click();
   }
}

class NES : IConsole
{
    public int MaxControllers
    {
        get { return 2; }
    }

   public void PlayGame(IGame game)
   {
       InsertCartridge(game);
       TurnOn();
   }
}
Это было полезно?

Решение

В Ruby нет интерфейсов, поскольку Ruby - динамически напечатанный язык. Интерфейсы в основном используются для разных классов, взаимозаменяемых без нарушения безопасности типа. Ваш код может работать с каждой консолью, пока она ведет себя как консоль, которая в C # означает, что Iconsole Iconsole. «Утка, набрав» - это ключевое слово, которое вы можете использовать, чтобы догнать динамические языки способом борьбы с такими проблемами.

Далее вы можете и должны писать тесты подразделения, чтобы проверить поведение вашего кода. У каждого объекта есть respond_to? Метод вы можете использовать в своем Assert.

Другие советы

Ruby имеет Интерфейсы Как и любой другой язык.

Обратите внимание, что вы должны быть осторожны, чтобы не ввязать концепцию Интерфейс, который является абстрактным спецификацией обязанностей, гарантий и протоколов единицы с концепцией interface Это ключевое слово в языках программирования Java, C # и VB.Net. В Ruby мы используем прежнее все время, но последнее просто не существует.

Очень важно отличить два. Что важно, это Интерфейс, не interface. Отказ То interface рассказывает вам почти ничего полезного. Ничто не демонстрирует это лучше, чем интерфейсы маркера В Java, которые являются интерфейсами, которые вообще не имеют членов: просто посмотрите на java.io.Serializable и java.lang.Cloneable; те два interfaceS значит очень разные вещи, но у них есть Точно так же подпись.

Итак, если два interfaceS, что означает разные вещи, имеют одинаковую подпись, что точно это interface даже гарантировать вам?

Еще один хороший пример:

interface ICollection<T>: IEnumerable<T>, IEnumerable
{
    void Add(T item);
}

Что Интерфейс из System.Collections.Generic.ICollection<T>.Add?

  • что длина коллекции не уменьшается
  • что все предметы, которые были в коллекции раньше, все еще там
  • тот item в коллекции

И какие из них на самом деле проявляется в interface? Никто! В interface что говорит, что Add Метод должен даже добавлять вообще, это может быть так же хорошо удалять элемент из коллекции.

Это совершенно действительная реализация этого interface:

class MyCollection<T>: ICollection<T>
{
    void Add(T item)
    {
        Remove(item);
    }
}

Еще один пример: где в java.util.Set<E> На самом деле это говорит, что это, вы знаете, набор? Нигде! Или точнее, в документации. На английском.

В значительной степени все случаи interfaces, как от Java, так и .NET, все соответствующий Информация на самом деле в документах, а не в типах. Итак, если типы все равно не говорят вам ничего интересного, зачем держать их вообще? Почему бы не придерживаться только документации? И это именно то, что делает Ruby.

Обратите внимание, что есть Другие Языки, в которых Интерфейс может фактически быть описан значимым образом. Тем не менее, эти языки обычно не вызывают конструкции, которая описывает Интерфейс "interface«Они называют это type. Отказ В зависимому языку программирования, вы можете, например, выразить свойства, которые sort Функция Возвращает коллекцию одинаковой длины, что и оригинал, что каждый элемент, который находится в оригинале, также находится в отсортированном сборе, и перед меньшим элементом не появится более крупный элемент.

Так что, короче говоря: Ruby не имеет эквивалента Java interface. Отказ Это делает Однако иметь эквивалент Java Интерфейс, И это точно так же, как в Java: Документация.

Также, как в Яве, Приемные тесты можно использовать для указания Интерфейси а также.

В частности, в Руби, Интерфейс объекта определяется тем, что он может делать, не то, что class есть, или что module это смешивается. Любой объект, имеющий << Метод можно добавить. Это очень полезно в модульных тестах, где вы можете просто пройти в Array или а String вместо более сложного Logger, даже не смотря на Array и Logger не разделяйте явную interface кроме того, что у них обоих есть метод под названием <<.

Другой пример есть StringIO, который реализует то же самое Интерфейс в виде IO и, таким образом, большая часть Интерфейс из File, но не разделяя каким-либо общим предком помимо Object.

Интерфейсы обычно вводятся на статические типизированные языки OO, чтобы составить отсутствие нескольких наследований. Другими словами, они больше необходимого зла, чем что-то полезное как таковой.

Рубин, с другой стороны:

  1. Динамически набранный язык с «стиркой утки», поэтому, если вы хотите вызвать метод foo На двух объектах им не нужно ни унаследовать тот же класс предков, ни реализовать тот же интерфейс.
  2. Поддерживает многократное наследование посредством концепции микс, снова не требует интерфейсов здесь.

Ruby на самом деле не имеет их; Интерфейсы и контракты обычно живут больше в статическом мире, а не динамично.

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

Ruby использует концепцию модулей в качестве подставки (вроде) для интерфейсов. Шаблоны дизайна в Ruby имеют много действительно отличных примеров от различий между двумя понятиями и почему Ruby выбирает более гибкую альтернативу интерфейсам.

http://www.amazon.com/design-patterns-ruby-russ-olsen/dp/0321490452.

У jorg есть хорошая точка, Ruby имеет интерфейсы, просто не ключевое слово. Читая некоторые ответы, я думаю, что это отрицательный на динамических языках. Вместо того, чтобы использовать интерфейс через язык, вы должны создавать модульные тесты вместо того, чтобы иметь методы Catch Compiler, не реализованные. Это также облегчает понимание метода сложнее для рассуждения, поскольку вы должны охотиться на то, что является объектом, когда вы пытаетесь это позвонить.

Возьми в качестве примера:

def my_func(options)
  ...
end

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top