Определение нескольких типов пробежек - PullRequest
0 голосов
/ 08 марта 2019

Экспериментируя с дженериками в Swift, я столкнулся с этой проблемой и не смог найти ответ.

Скажите, у меня есть следующий код:

protocol Component {
}

protocol Contains {
    associatedtype CompType: Component
    var components: [CompType] { get set }
}

Здесь типы, которые реализуют Contains, должны иметь возможность хранить любой тип, который реализует протокол Component, определенный их typealias. Если я расширю код до следующего, он будет работать как положено.

protocol Component {
}

struct SomeComponent: Component {
    init() {
    }
}

struct AnotherComponent: Component {
    init() {
    }
}

protocol Contains {
    associatedtype CompType: Component
    var components: [CompType] { get set }
}

struct Container: Contains {
    typealias CompType = SomeComponent
    var components: [SomeComponent]
}

var x = Container(components: [SomeComponent()])  // works perfectly!
var y = Container(components: [AnotherComponent()])  // fails as expected

Наконец, вопрос: возможно ли заставить Container.components принимать и SomeComponent, и AnotherComponent, но отклонить другие типы, которые реализуют протокол Component? Другими словами, может ли typealias содержать более одного типа?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 08 марта 2019

Вы можете соответствовать нескольким протоколам

typealias CompType = SomeComponent & AnotherComponent

Или вы можете изменить логику

protocol Component {
}

struct SomeComponent: Component {
    init() {
    }
}

struct AnotherComponent: Component {
    init() {
    }
}

protocol Contains {
    var components: [Component] { get set }
}

struct Container: Contains {
    var components: [Component]
}

var x = Container(components: [SomeComponent()])
var y = Container(components: [AnotherComponent()])
0 голосов
/ 08 марта 2019

Я не думаю, что вам нужно associatedtype вообще

protocol Component {
}

struct SomeComponent: Component {
    init() {
    }
}

struct AnotherComponent: Component {
    init() {
    }
}

protocol Contains {
    var components: [Component] { get set }
}

struct Container: Contains {
    var components: [Component]
}

var x = Container(components: [SomeComponent()])
var y = Container(components: [AnotherComponent()])

Используйте associatedtype в протоколах, когда вам нужно указать тип.

В этом случае вы не хотите указывать, потому что хотите иметь возможность принимать конформер к протоколу

0 голосов
/ 08 марта 2019

Псевдоним типа служит для разрешения общего связанного типа.Это должно разрешить это к одному типу однозначно;это то, что является разрешением.

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

associatedtype CompType: Component

Вы использовали общее ограничение компонента.Если это не то, что вы хотели, вы не должны были так все настраивать.Как предлагали другие, если вы хотите, чтобы только SomeComponent и AnotherComponent удовлетворяли общему ограничению, вам нужно будет использовать протокол, который принимают только SomeComponent и AnotherComponent.

...