在不使用泛型的情况下编写我的协议的任何方法,或者在其他情况下使用关联类型的解决方法?

时间:2019-05-30 15:26:16

标签: swift generics enums protocols associated-types

我有一个协议BluetoothLeAdvertiser,并且我希望遵循几种不同的Scale结构(即BluetoothLeAdvertiserScaleDetails等)。然后,我想要一个不同的协议MajorScale,该协议具有类型DiminishedScale的变量ComboChord,根据其他变量的不同,其规模也不同。问题是我无法在scale中将ScaleDetails变量分配为类型scale,因为我不知道如何在不使用关联类型的情况下编写协议。

每个比例尺使用不同的模式枚举(例如,ComboChord的{​​{1}}和ScaleDetails的{​​{1}})。每个标度都有返回该特定标度结构的一个或多个实例的函数。因此,如果在我的Mode.SevenDeg协议中不使用泛型,我将看不到前进的道路。我试图在不使用类的情况下编写此代码,但在必要时愿意使用它们。我也确实在尝试避免对秤进行类型转换,因为我不想每次调用它时都必须列出每种秤的可能性。我该如何解决?

ScaleDetails协议

MajorScale

ComboChord协议

Mode.TwoDeg

模式枚举

DiminishedScale

主要规模

ScaleDetails

DiminishedScale

protocol ScaleDetails {
    associatedtype ScaleMode where ScaleMode: RawRepresentable
    associatedtype T
    //...
    var root: Root { get set }
    var mode: ScaleMode { get set }
    //...
    init(_ root: KeyName.Root, mode: ScaleMode)

    func translated(by offset: Int) -> T

    func enharmSwapped() -> T
    //...
    mutating func switchMode(mode: ScaleMode)

    func getParallelModes(root: KeyName.Root) -> [T]
    func getParentModes() -> [T]
}

KeyName.Root

protocol ComboChord {
    var scale: ScaleDetails // doesn't work

    static var validCombos: [[Int]] { get }

    var quality: Suffix { get }
    var uprStrNotes: [Int] { get }
/*
error: "Protocol can only be used as a generic constraint
because it has Self or associatedType requirements"
*/
}

enum Mode {

    enum TwoDeg: Int, CaseIterable, ModeProtocol {
        case one = 0, two

        //...
    }

    enum SevenDeg: Int, CaseIterable, ModeProtocol {
        case one = 0, two, three, four, five, six, seven

        //...
    }
}

DetailChord

(大量缩减长度,原始长度约为1400行)

struct MajorScale: ScaleDetails {
    var root: Root
    var mode: Mode.SevenDeg

    //...

    init(_ root: KeyName.Root, mode: Mode.SevenDeg = .one) {
        self.root = Root(root)
        self.mode = mode
        self.enharm = root.r.enharm
    }

    func translated(by offset: Int) -> MajorScale {
        //...do things to the scale

        return MajorScale(newRootKey, mode: mode)
    }

    //...
    mutating func switchMode(mode: Mode.SevenDeg) {
        self.mode = mode
    }

    //...

    func enharmSwapped() -> MajorScale {
        //...do things to the scale

        return MajorScale(newRootKey, mode: mode)
    }

    func getParallelModes(root: KeyName.Root) -> [MajorScale] {
        return Mode.SevenDeg.allCases.map {MajorScale(root, mode: $0)}
    }

    func getParentModes() -> [MajorScale] {
        //...code to get array of scales
        return parentModes
    }
}

1 个答案:

答案 0 :(得分:1)

不确定是否适合您的用法,但是也许您也可以使ComboChord通用

protocol ComboChord {
    associatedtype Scale: ScaleDetails
    var scale: Scale { get }
}

然后像这样使用它

struct Chord: ComboChord {

    var scale: DiminishedScale

}