Type Erasure with Pokemon---swift的类型擦除

拟墨画扇 提交于 2019-12-06 10:46:35

我感觉这个是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() }

 

 

 

 

 

  1. class Pet { }
  2. class Dog: Pet { }
  3. class Cat: Pet { }
  4. // 1. 隐藏具体宠物类型信息
  5. let pets: [Pet] = [Dog(), Cat()]

 

https://github.com/bignerdranch/type-erasure-playgrounds/blob/master/playgrounds/Pokemon_erasure.playground/Contents.swift

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!