В swift, почему я не могу создать экземпляр протокола, если у него есть инициализатор? - PullRequest
0 голосов
/ 25 июня 2018

Я понимаю, что обычно я не могу создать экземпляр протокола. Но если я включу инициализатор в протокол, то компилятор наверняка знает, что когда протокол используется структурой или классом позже, у него будет init, который он может использовать? Мой код как показано ниже и строка:

protocol Solution {
  var answer: String { get }
}

protocol Problem {
  var pose: String { get }
}

protocol SolvableProblem: Problem {
  func solve() -> Solution?
}

protocol ProblemGenerator {
  func next() -> SolvableProblem
}

protocol Puzzle {
  var problem: Problem { get }
  var solution: Solution { get }

  init(problem: Problem, solution: Solution)
}

protocol PuzzleGenerator {
  func next() -> Puzzle
}

protocol FindBySolvePuzzleGenerator: PuzzleGenerator {
  var problemGenerator: ProblemGenerator { get }
}

extension FindBySolvePuzzleGenerator {
  func next() -> Puzzle {
    while true {
      let problem = problemGenerator.next()
      if let solution = problem.solve() {
        return Puzzle(problem: problem, solution: solution)
      }
    }
  }
}

Линия:

return Puzzle(problem: problem, solution: solution)

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

Ответы [ 5 ]

0 голосов
/ 25 июня 2018

Но если я включу инициализатор в протокол, то компилятор наверняка знает, что когда протокол используется структурой или классом позже, у него будет init, который он может использовать?

Протоколы должны быть приняты классами, и может быть дюжина различных классов, которые все принимают ваш протокол Puzzle. Компилятор не знает, какой из этих классов создать.

Протоколы дают нам возможность создавать интерфейсы без сложного множественного наследования. В языке множественного наследования, таком как C ++, вам приходится иметь дело с тем фактом, что один класс D может наследоваться от двух других классов, B и C, и эти два класса могут иметь методы или переменные экземпляра с одно и то же имя Если они оба имеют methodA(), а B::methodA() и C::methodA() различаются, какой вы используете, когда кто-то вызывает D, унаследованный methodA()? Хуже того, что если B и C оба являются производными от общего базового класса A? Протоколы избегают многого из этого, поскольку не являются непосредственно инстанцируемыми, и в то же время обеспечивают полиморфизм интерфейса, который делает привлекательным множественное наследование.

0 голосов
/ 25 июня 2018

Я понимаю, что не могу этого сделать - я просто хочу понять, почему компилятор не может этого сделать?

Поскольку протоколы в Swift представляют абстракцию механизм. Когда дело доходит до абстракции, вы можете думать о нем как о шаблоне, нам не нужно заботиться о деталях его поведения или его свойствах; Таким образом, он не создает сцены, чтобы создать из него объект.

В качестве примера из реального мира, подумайте, что я только что сказал «Таблица» (как абстрактный уровень), я был бы совершенно уверен, что вы поймете, о чем я говорю! тем не менее, мы не упоминаем подробности о нем (например, материал или сколько у него ног ...); В какой-то момент, если я скажу «создать таблицу для меня» (создать экземпляр объекта), у вас будет вопрос о спецификациях! и именно поэтому компилятор не позволит вам создавать объекты напрямую из протокола. В этом смысл абстрагирования вещей.

Кроме того, проверка: Почему нельзя создать объект абстрактного класса? может быть полезным.

0 голосов
/ 25 июня 2018

К сожалению, swift не позволяет этого даже с таким "взломом"

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

0 голосов
/ 25 июня 2018

Представьте себе протоколы прилагательных. Movable говорит, что вы можете move это, Red говорит, что у него есть color = "red" ... но они не говорят, что такое это . Вам нужно существительное. Красный, Подвижный Автомобиль. Вы можете создать экземпляр автомобиля, даже если мало информации. Вы не можете создать экземпляр Red.

0 голосов
/ 25 июня 2018

Когда вы создаете экземпляр объекта, операционная система должна знать, как распределять и обрабатывать объекты такого типа в памяти: это ссылочный тип (классы)?Сильная, слабая или неподтвержденная ссылка?Или это тип значения (Structs, Strings, Int и т. Д.)?

Типы ссылок хранятся в куче, а типы значений - в стеке. Здесь является подробным объяснением различий между ними.

Могут быть созданы только типы-объекты Reference и Value (объекты).Таким образом, могут быть созданы только объекты, которые соответствуют этому протоколу, а не сам протокол.Протокол - это не объект, это общее описание или схема определенного поведения объектов.

Что касается инициализации, то, что Apple docs говорит:

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

...