簡體   English   中英

多層次深層通用/協議的Swift通用和協議問題

[英]Swift Generics and Protocol issues for multi-level-deep generics/protocol

我正計划為芝加哥兒童制作一個閃存卡應用程序,只要他們能夠遵守相同的協議,它就可以提出很多問題。 理想情況下,會有許多不同難度的游戲,並且視圖將能夠使用所有游戲,因為所有游戲都遵循相同的協議。 我希望每個轉彎都有能力采用完全不同的結構,只要它是相等的即可。

我覺得我已經接近了,但是我無法終生解決如何讓游戲獲取任何數據而又不會出錯的感覺……我覺得我已經接近了,但是無法過去這個減速帶。

我不斷收到諸如“ TurnDefinable只能用作通用約束,因為它具有自定義或關聯類型要求”之類的錯誤。

protocol GameDefinable {
    associatedtype TurnType: TurnDefinable
    var turns: [TurnType] { get }
}

class Game<T: TurnDefinable>: GameDefinable {
    var turns: [T]

    init(turns: [T]) {
        self.turns = turns
    }
}

class Turn<A: AnswerDefinable>: TurnDefinable {
    var question: String
    var correctAnswer: A
    var answers: [A]

    init(question: String, answers: [A], correctAnswer: A) {
        self.question = question
        self.answers = answers
        self.correctAnswer = correctAnswer
    }
}

protocol TurnDefinable {
    associatedtype AnswerType
    /// Localized string to ask the user a question they must answer
    var question: String { get }
    /// Array of possible answers
    var answers: [AnswerType] { get }
    /// Correct answer per turn
    var correctAnswer: AnswerType { get }
}

protocol AnswerDefinable: Equatable {
    // Will have more stuff here like localized formatted string, etc
}

// Just created this test pretending our answers will be Ints
struct ExampleOfAnAnswerStruct: AnswerDefinable {
    static func == (lhs: ExampleOfAnAnswerStruct, rhs: ExampleOfAnAnswerStruct) -> Bool {
        return lhs.testInteger == rhs.testInteger
    }

    // Just created this to get the equatable
    var testInteger = 0
}


struct ExampleOfAnAnswerStruct2: AnswerDefinable {
    var string: String
    static func == (lhs: ExampleOfAnAnswerStruct2, rhs: ExampleOfAnAnswerStruct2) -> Bool {
        return lhs.string == rhs.string
    }
}

任何幫助將非常感謝...

編輯:我現在離我更近了,我只需要弄清楚如何使用兩個具有不同答案類型的回合

let turnExample1 = Turn<ExampleOfAnAnswerStruct>(question: "Which is the lonliest number?", answers: [ExampleOfAnAnswerStruct(testInteger: 1), ExampleOfAnAnswerStruct(testInteger: 2), ExampleOfAnAnswerStruct(testInteger: 3)], correctAnswer: ExampleOfAnAnswerStruct(testInteger: 1))
let turnExample2 = Turn<ExampleOfAnAnswerStruct2>(question: "You say goodbye, and i say ...", answers: [ExampleOfAnAnswerStruct2(string: "hello"), ExampleOfAnAnswerStruct2(string: "goodbye")], correctAnswer: ExampleOfAnAnswerStruct2(string: "hello"))

let testGame = Game(turns: [turnExample1, turnExample2])

我好親密! 感謝到目前為止的所有幫助!

我有個主意,但我不確定。

如果泛型類的兩個實例化都使用相同的類型(例如整數),則它們只有相同的類型。 在協議中具有associatedType可能意味着一個實例不能與另一個實例相同地使用。

使用TurnDefinable意味着兩個實例化可以具有不同的類型,並且編譯器可能不喜歡在數組中使用不同的類型(不可用)。
無法使用的原因是,您不能一視同仁,調用相同的函數,訪問相同的變量。
具有不同功能簽名的功能不再是同一功能。

如果編譯器只是忽略以下內容,您將如何編寫?

for turn in turns {
    turn.answers.first!.X // ???
}

您可以使用一個空的Answer協議並在其上鍵入switch。 也許有幫助。

protocol Answer {}

for turn in turns {
    for answer in turn.answers {
        switch answer {
        case let type1 = answer as AnswerType1:
            break //
        case let type2 = answer as AnswerType2:
            break
        default:
            fatalError("Answer type unknown \(type(of: Answer))")
        }
    }
}

您不能擁有TurnDefinable類型的數組,因為您已經看到它是一個具有關聯類型的協議。

您需要調整GameDefinable協議,使其具有自己的關聯類型,您可以將其用作數組的類型:

protocol GameDefinable {
    associatedtype TurnType: TurnDefinable
    var turns: [TurnType] { get }
}

然后,您可以向您的Game類添加一個通用參數,該參數將用作GameDefinable協議的關聯類型Turn<ExampleOfAnAnswerStruct>如果您想限制游戲到某種類型):

class Game<T: TurnDefinable>: GameDefinable {
    var turns: [T]

    init(turns: [T]) {
        self.turns = turns
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM