#swift
Вопрос:
У меня есть следующий код для создания массива различных создателей в Swift. Я использовал метод стирания типов, чтобы заполнить один и тот же массив разными типами создателей. Когда я пытаюсь создать список, он выдает мне сообщение об ошибке.
error: heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional
let creators = [AnyPokemonCreator(PikachuCreator()), AnyPokemonCreator(BulbasaurCreator())]
import UIKit
struct Pikachu {
let name: String
let powers: [String]
}
struct Bulbasaur {
let name: String
let powers: [String]
}
protocol PokemanCreator {
associatedtype Pokemon
func create() -> Pokemon
}
struct BulbasaurCreator: PokemanCreator {
typealias Pokemon = Bulbasaur
func create() -> Pokemon {
return Bulbasaur(name: "Bulbasaur", powers: ["Vine Whip"])
}
}
struct PikachuCreator: PokemanCreator {
typealias Pokemon = Pikachu
func create() -> Pokemon {
return Pikachu(name: "Pikachu", powers: ["Electric"])
}
}
struct AnyPokemonCreator<Pokemon>: PokemanCreator {
private let _create: () -> Pokemon
init<Creator: PokemanCreator>(_ creator: Creator) where Creator.Pokemon == Pokemon {
_create = creator.create
}
func create() -> Pokemon {
return _create()
}
}
// THIS LINE GIVES ERROR
let creators = [AnyPokemonCreator(PikachuCreator()), AnyPokemonCreator(BulbasaurCreator())]
Комментарии:
1. Беда в том, что ваш стирающий аппарат по-прежнему является универсальным. Разные универсальные типы-это разные типы. Таким образом, у вас нет массива одного типа элементов.
2. Вы не можете ввести-стереть функцию, которая имеет разные возвращаемые значения. Какой тип возврата
creators[0].create()
? Он должен быть таким же, как типcreators[1].create()
, или вы не «стерли» какие-либо типы. И у вас не может быть множества таких. Что бы вы хотели сделать с создателями? Какой код будет использовать его без использованияas
? Это подскажет нам, как это исправить. (Вам, вероятно, не нужен или не нужен ластик типа здесь.)3. Я пытаюсь стереть типы, чтобы у меня был массив создателей покемонов. Имейте в виду, что PokemonCreator-это протокол, содержащий связанный тип.
4. Этот подход не позволяет создавать массив из какого-либо создателя . Это невозможно, если только все покемоны не одного типа (обратите внимание, что в примере массив работает только потому, что все задействованные типы-электромобили; вы не можете поместить в этот массив разные типы автомобилей). Тем не менее, вам, вероятно, вообще не нужен стирающий тип. Они не являются волшебной пулей и в большинстве случаев указывают на то, что у вас есть проблема с дизайном. (Не всегда; для этого есть веские причины. Но они встречаются гораздо реже, чем люди думают.) Если вы объясните, для чего вам нужен вызывающий код, мы можем помочь.
5. Какова следующая строка кода? Когда ты пишешь
for creator in creators { ... }
. Что войдет в блок в вашей реальной программе?
Ответ №1:
Сначала ваш init говорит, что вы приведете аргумент, которого явно не делаете . Во-вторых, что именно вы пытаетесь сделать? Если вы хотите, чтобы кто-то придерживался протокола, просто скажите, что у меня есть то, что, согласно протоколу, мне нужно. т. е.:
protocol PokemanCreator {
func create() -> Pokemon
}
class SomeSuperClass {
var somethingShared: SomeValue?
}
class BulbasaurCreator: Pokemon, PokemanCreator {
var someBulbasaurVariable: SomeType = SomeInitialValue
var/let name: String
var/let powers: [String]
static func create() -> Pokemon {
super.init()
return Bulbasaur(name: "Bulbasaur", powers: ["Vine Whip"])
}
}
}
Комментарии:
1. Я хочу создать массив PokemonCreator. PokemonCreator-это протокол с соответствующим типом.
2. Я не наследую никакой структуры. Пожалуйста, взгляните на код.