Протокол Swift, использующий другой протокол, вызывает ошибку - PullRequest
0 голосов
/ 04 июля 2018

Я работаю в Swift 4.

Я хочу определить проблему.

Проблема состоит из Вопроса и Ответа.

Вопрос может быть любым из: String, Int, [Int], Image, [Image] или какого-то нового типа, не определенного, или может представлять собой некоторую комбинацию из вышеперечисленного.

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

(например, вопрос = (Изображение: «Что это за животное?), Ответ = (« Кошка »))

Так что я подумал, что протоколы - это путь:

protocol Posable {
  var pose: String { get }
}

protocol Answerable: Hashable {
  var answer: String { get }
}

protocol Puzzle {
  var problem: Posable { get }
  var solution: Answerable { get }
}

Я сделал Answerable Hashable, потому что хочу иметь возможность сравнивать ответы и создавать наборы ответов.

Но я получаю решение: Ответная строка:

'Протокол' Answerable 'может использоваться только в качестве общего ограничения, поскольку у него есть требования к Self или связанный тип.

Я понимаю, почему это так, но ...

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

Я стремлюсь реализовать протоколы, если это возможно, частично, чтобы я узнал о них.

Ответы [ 2 ]

0 голосов
/ 04 июля 2018

Я не уверен, но вы можете удалить Hashable из Answerable.

protocol Posable {
    var pose: String { get }
}

protocol Answerable {
    var answer: String { get }
}

protocol Puzzle {
    var problem: Posable? { get }
    func getSolution<T: Hashable & Answerable>() -> T
}
0 голосов
/ 04 июля 2018

Я бы решил это с помощью дженериков:

import UIKit

struct Posable<T> {
    var pose: T
}

struct Answerable<T> {
    var answer: T
}

extension Answerable: Equatable where T: Equatable {
    static func ==(lhs: Answerable<T>, rhs: Answerable<T>) -> Bool {
        return lhs.answer == rhs.answer
    }
}

extension Answerable: Hashable where T: Hashable {
    var hashValue: Int {
        return answer.hashValue
    }
}

struct Puzzle<T, U> {
    var problem: Posable<T>
    var solution: Answerable<U>
}

let image = UIImage() // Image of a cat
let pose = Posable<(UIImage, String)>(pose: (image, "What type of animal is this?"))
let solution = Answerable<String>(answer: "A cat")

let myPuzzle = Puzzle<(UIImage, String), String>(problem: pose, solution: solution)

Обобщения позволяют создавать очень многократно используемый код! Здесь вы можете использовать любой класс в качестве вопроса или ответа.

С типизацией Swift: вы также можете упростить инициализацию:

let image = UIImage() // Image of a cat
let pose = Posable(pose: (image, "What type of animal is this?"))
let solution = Answerable(answer: "A cat")

let myPuzzle = Puzzle(problem: pose, solution: solution)
...