我感觉这个是swift的设计缺陷。
类型擦除:解决泛型类型作为公用类型的问题
是抽象的公用机制的一种实现方式。
1)类型擦除并不能解决类型不一致的兼容问题,只能解决类似继承一致性的兼容问题。
2)擦除类型后的抽象类型,其类型信息仍然存在,只是需要保持逻辑一致性。
import Foundation |
|
|
|
|
protocol Pokemon { |
|
associatedtype Power |
|
func attack() -> Power |
|
} |
|
|
|
struct Pikachu: Pokemon { |
|
func attack() -> 🌩 { |
|
return 🌩() |
|
} |
|
} |
|
|
|
struct Charmander: Pokemon { |
|
func attack() -> 🔥 { |
|
return 🔥() |
|
} |
|
} |
|
|
|
// power types |
|
struct 🔥 { } |
|
struct 🌩 { } |
|
|
|
// MARK: - Abstract base class |
|
class _AnyPokemonBase<Power>: Pokemon { |
|
init() { |
|
guard type(of: self) != _AnyPokemonBase.self else { |
|
fatalError("_AnyPokemonBase<Power> instances can not be created; create a subclass instance instead") |
|
} |
|
} |
|
func attack() -> Power { |
|
fatalError("Must override") |
|
} |
|
} |
|
// MARK: - Box container class |
|
fileprivate final class _AnyPokemonBox<Base: Pokemon>: _AnyPokemonBase<Base.Power> { |
|
var base: Base |
|
init(_ base: Base) { self.base = base } |
|
fileprivate override func attack() -> Base.Power { |
|
return base.attack() |
|
} |
|
} |
|
// MARK: - AnyPokemon Wrapper |
|
final class AnyPokemon<Power>: Pokemon { |
|
private let box: _AnyPokemonBase<Power> |
|
init<Base: Pokemon>(_ base: Base) where Base.Power == Power { |
|
box = _AnyPokemonBox(base) |
|
} |
|
func attack() -> Power { |
|
return box.attack() |
|
} |
|
} |
|
|
|
// Use AnyPokemon type directly |
|
let pokemon: AnyPokemon = AnyPokemon(Pikachu()) |
|
pokemon.attack() |
|
|
|
// Add a new electric Pokemon |
|
class Jolteon: Eevee, Pokemon { |
|
func attack() -> 🌩 { |
|
return 🌩() |
|
} |
|
} |
|
class Eevee {} |
|
|
|
// Iterate over a collection of Electric Pokemon |
|
let electricPokemon = [AnyPokemon(Pikachu()), AnyPokemon(Jolteon())] |
|
electricPokemon.map() { $0.attack() } |
- class Pet { }
- class Dog: Pet { }
- class Cat: Pet { }
- // 1. 隐藏具体宠物类型信息
- let pets: [Pet] = [Dog(), Cat()]
https://github.com/bignerdranch/type-erasure-playgrounds/blob/master/playgrounds/Pokemon_erasure.playground/Contents.swift