От новичка до гуру: Курсы программирования на CyberDuff

Рекомендуемый способ переопределить метод для ограниченного расширения в swift, избегая сообщения Неоднозначное использование «xxx»

Я знаю, почему у меня появляется сообщение об ошибке, поэтому вопрос больше о том, что есть в Swift 2.x раз, рекомендуемый способ сделать это.

Данные, которые я хочу представить, концептуально представляют собой не что иное, как Array специализированного класса/структуры с некоторыми дополнительными методами, которые семантически имеют смысл только для этого конкретного типа элементов.

Swift предоставляет нам ограниченные расширения, которые отлично подходят для этого.

Чтобы конкретизировать мою проблему, скажем, мне нужна колода карт. Итак, для Card я могу определить протокол, который позволит мне сделать ограниченное расширение на Array.

// Define a protocol for specializing Arrays of Cards
protocol _CardType {}
extension Card: _CardType {}

А потом

typealias Deck = [Card]

extension Array where Element : _CardType {
}

Внутри этого расширения я могу определить все функции, которые мне нужны, связанные с колодой карт, скажем, перетасовку, разрезание или что-то еще.

Я мог бы также внутри этого расширения написать что-то вроде

    var description: String {
      return "Deck: " + self.map { "\($0)" }.joinWithSeparator(",")
    }

Это было бы хорошо и хорошо, пока я не попытаюсь в какой-то момент написать где-нибудь в другом месте.

  func showDeck() {
    print(deck.description)
  }

Это даже не скомпилируется, получив сообщение

Неоднозначное использование слова «описание».

Конечно, здесь мне удалось получить версию описания Array и версию моего расширения, и на данный момент компилятор не может сказать, какая из них правильная.

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

Свойство не переопределяет какое-либо свойство своего суперкласса

Простые решения в этом выдуманном сценарии заключались бы в том, чтобы определить для Deck другую функцию prettyDescription, чтобы не пришлось пытаться переопределить описание или использовать модель «имеет-а» вместо модели «есть-а». (т.е.) Deck будет иметь свойство с массивом карт.

Дело в том, что я хочу воспользоваться уже существующим кодом за пределами моего класса, где уже есть функциональность, которая ожидает отношение «есть-а» (в данном случае наличие description).

В придуманном сценарии функция description является стандартным способом вывода Array, поэтому я хочу, чтобы Deck соответствовало ей.

Рад услышать мысли о наилучшем способе приблизиться к этому.


  • Я не могу воспроизвести проблему. Пожалуйста, предоставьте достаточный код, чтобы я мог скопировать ваш код в проект, попытаться скомпилировать его и получить вашу ошибку. (На первый взгляд проблема выглядит как проблема с deck в deck.description, которая не определена в показанном вами контексте, поэтому невозможно сказать, что это может быть.) 21.05.2016
  • Могут быть особые причины этого не делать, но задумывались ли вы о том, чтобы сделать Card классом, наследуемым от CardType ? Кроме того, причина, по которой вы не можете override, заключается в том, что вы ничего не создаете в подклассах. Наконец, и это более фундаментальная проблема, то, что вы делаете, не обязательно является очень хорошим способом сделать это. Я бы рекомендовал создать протокол CardType, структуру или класс Card, наследуемый от CardType, и, наконец, оболочку вокруг Deck, например класс, в котором переменная экземпляра является Array<Card> или Array<CardType>. Соблюдайте CustomStringConvertible и все будет хорошо 21.05.2016
  • Спасибо @мат. Здесь я только что загрузил суть, которая будет воспроизводиться: 22.05.2016
  • Но это не скомпилируется, не так ли? Вы нигде не определили simpleDescription, вы не импортируете целевой модуль приложения в тест... Это не имеет смысла. 22.05.2016
  • @AlexandreCassagne - единственная причина для использования протокола _CardType заключается в том, что в данном примере Card является простой структурой, а из документации Apple вы пишете ограничение типа, помещая одно ограничение класса или протокола после имени параметра типа, разделенного символом двоеточие, как часть списка параметров типа. Поскольку strict не является ни классом, ни протоколом, мне нужно было использовать этот обходной путь. 22.05.2016
  • @JuanCarlosMéndez Недавно я переписал много кода, потому что мы решили изменить основные типы. Я понимаю, что вы имеете в виду, но было бы разумно рассмотреть возможность использования разных базовых типов. Конечно, я ничего не знаю о вашем коде, но подумайте об этом. 22.05.2016
  • @matt - я напечатал это по существу в качестве примера. Предположим, что у Rank есть метод simpleDescription, возвращающий строку ранга карты (A,2,3,...,J,Q,K), а у Suit также есть метод simpleDescription со строкой масти (♣, ♠,...) 22.05.2016
  • Нужен не пример, а воспроизводимый случай. Однако, достаточно модифицировав, я смог воспроизвести достаточно хорошо. Спасибо. 22.05.2016
  • где уже есть функциональность, которая ожидает отношение «есть-а» (в данном случае наличие описания). Но, если это все, что вам нужно, то, как вам уже сказали, сделайте совершенно другую структуру колоды и примите CustomStringConvertible . Это именно то, для чего это нужно. 22.05.2016

Ответы:


1

Если я правильно понял ваш вопрос, вы не можете сделать это с расширением из документов Apple:

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

Для переопределения существующей функциональности вам необходимо использовать суперкласс.

21.05.2016
  • Вы правы, из developer.apple.com/library /ios/documentation/Swift/Conceptual/ — вот почему я получаю ошибку «Неоднозначное использование описания». Я пытаюсь понять, как люди будут использовать ограниченные расширения. 22.05.2016
  • @JuanCarlosMéndez Неважно, является ли это ограниченным расширением, поведение такое же, вы просто не можете этого сделать, использовать другое имя метода в своем расширении или суперкласс. Я согласен, что было бы неплохо, если бы это было возможно 22.05.2016
  • @JuanCarlosMéndez Кажется, вы можете в ????3.1: hackingwithswift.com/swift3-1 26.03.2017
  • @JuanCarlosMéndez Все еще не может переопределить существующие функции - developer.apple.com/library/prerelease/content/documentation/. 26.03.2017

  • 2

    Данные, которые я хочу представить, концептуально являются не чем иным, как массивом специализированного класса/структуры с некоторыми дополнительными методами, которые семантически имеют смысл только для этого конкретного типа элементов.

    Swift дает нам ограниченные расширения, которые отлично подходят для этого.

    Нет, они не; они совсем не для этого. Вот почему у вас проблемы; ваши посылки фатально ошибочны, поэтому то, что из них следует, несостоятельно.

    Давайте посмотрим на детали того, с чем столкнулась ваша попытка сделать это.

    • Swift Array уже реализует description. Колода - это просто массив. Вы не можете повторно реализовать существующий description в расширении. Сюрприз здесь только в том, что ваша попытка сделать это компилируется в первую очередь; Я бы назвал это багом, хотя могу и ошибаться.

    • Вам также мешает тот факт, что Array в Swift — это структура, а не класс. (Вот почему вы не можете переопределить description; нет такой вещи, как переопределение, когда речь идет о структуре, поскольку нет наследования.)

    Таким образом, вся ваша архитектура попыток использовать расширение, чтобы сделать колоду своего рода массивом, ошибочна.

    Я бы посоветовал вместо того, чтобы пытаться использовать отношение "есть-отношение" между колодой и массивом, вы использовали отношение "имеет-а"; превратить колоду во что-то, что имеет массив карт (как свойство), принимает CustomStringConvertible и (следовательно) реализует свойство description. Это решит проблему красиво.

    21.05.2016
  • Я согласен с @matt, что компилируется странно, и я знаю, что пример несколько надуманный. Идея использования has-a подойдет для примера с колодой. Однако ключевой момент в первоначальном вопросе заключается в том, что из-за всех других классов моего программного обеспечения я бы настоятельно предпочел is-a вместо has-a. Отредактирую вопрос, потому что ваше разъяснение очень полезно 22.05.2016
  • Я не думаю, что ясно выражаюсь. На самом деле неважно, что вы предпочитаете. В структурах нет is-a, и попытка использовать расширения, чтобы притвориться, что существует, не сработает. 22.05.2016
  • Я согласен с @matt. @JuanCarlosMéndez, вы говорите, что «решительно предпочитаете» один подход, но, как я сказал в другом комментарии, с таким подходом вы упираетесь в стену. В этом случае вы должны создать класс или структуру, представляющую ваш Deck, который содержит массив ваших карточек. Реализовать CustomStringConvertible. 22.05.2016
  • Новые материалы

    Представляем Narwhal Technologies (Nrwl)
    6 декабря 2016 г. Маунтин-Вью, Калифорния С тех пор, как Виктор Савкин и я (Джефф Кросс) присоединились к команде Angular в Google на заре Angular 1, Angular продемонстрировал феноменальный..

    Путь AWS  — «Изучение машинного обучения — 10 начинающих ИИ и машинного обучения на AWS».
    Универсальный ресурсный центр для изучения искусственного интеллекта и машинного обучения. НОЛЬ или ГЕРОЙ, начните свое путешествие здесь. Получите решения и пройдите обучение у экспертов AWS...

    5 простых концепций Python, ставших сложными
    #заранее извините 1) Переменные x = 4 y = 5 Переменная в Python — это символическое представление объекта. После присвоения некоторого объекта переменной Python мы приобретаем..

    «Освоение вероятности: изучение совместной, предельной, условной вероятности и теоремы Байеса —…
    Виды вероятности: Совместная вероятность Предельная вероятность Условная вероятность Диаграмма Венна в вероятностях: В “Set Theory” мы создаем диаграмму Венна...

    Основы Spring: Bean-компоненты, контейнер и внедрение зависимостей
    Как лего может помочь нашему пониманию Когда мы начинаем использовать Spring, нам бросают много терминов, и может быть трудно понять, что они все означают. Итак, мы разберем основы и будем..

    Отслеживание состояния с течением времени с дифференцированием снимков
    Время от времени что-то происходит и революционизирует часть моего рабочего процесса разработки. Что-то более забавное вместо типичного утомительного и утомительного процесса разработки. В..

    Я предполагаю, что вы имеете в виду методы обработки категориальных данных.
    Я предполагаю, что вы имеете в виду методы обработки категориальных данных. Пожалуйста, проверьте мой пост Инструментарий специалиста по данным для кодирования категориальных переменных в..