多様なセルごちゃ混ぜ UITableView

型を値として扱ってると, キャストしづらい...

```Swift
/// 素直に `protocol 名前: class where Self: 継承元` とやると,
/// 「Redundant constraint 'Self' : 'AnyObject'」
/// とか言われるので, とりあえず回避してみた.
protocol AnyObjectProtocol: class {}

/// とあるビューコントローラに表示するセルは, このプロトコルに準拠する.
protocol MyTableViewCellProtocol: AnyObjectProtocol where Self: UITableViewCell {
    /// .xib ファイルの名前.
    static var XIB_NAME: String { get }

    /// Re-use Identifier.
    static var IDENTIFIER: String { get }

    /// 各種類別の, セルの高さ.
    static var HEIGHT: CGFloat { get }

    /// セルにデータをセットする, 共通のメソッド.
    func setMyTableViewData(_ data: String)
}
extension MyTableViewCellProtocol {
    ///
    /// 型を値として扱っているけれど, キャストしたい.
    ///
    /// こんな方法しか思い付かなかったが,
    /// もう少しスマートな方法があるのだろうか ?
    ///
    static func cast(from: UITableViewCell) -> Self? {
        return from as? Self
    }
}

/// Foo タイプのセル.
class MyTableViewFooCell: UITableViewCell, MyTableViewCellProtocol {
    static var XIB_NAME: String = "MyTableViewFooCell"
    static var IDENTIFIER: String = "MyTableViewFooCell"
    static var HEIGHT: CGFloat = 30
    func setMyTableViewData(_ data: String) {}
}

/// Bar タイプのセル.
class MyTableViewBarCell: UITableViewCell, MyTableViewCellProtocol {
    static var XIB_NAME: String = "MyTableViewBarCell"
    static var IDENTIFIER: String = "MyTableViewBarCell"
    static var HEIGHT: CGFloat = 80
    func setMyTableViewData(_ data: String) {}
}

/// Baz タイプのセル.
class MyTableViewBazCell: UITableViewCell, MyTableViewCellProtocol {
    static var XIB_NAME: String = "MyTableViewBazCell"
    static var IDENTIFIER: String = "MyTableViewBazCell"
    static var HEIGHT: CGFloat = 50
    func setMyTableViewData(_ data: String) {}
}

/// 多種のセルをごちゃ混ぜに持つテーブルビューを持つビューコントローラ.
class TestViewController: UIViewController
    , UITableViewDelegate
    , UITableViewDataSource
{
    /// セルのデータ.
    private struct CellData {
        /// セルのクラス.
        var cellClass: MyTableViewCellProtocol.Type

        /// セルのデータ.
        var data: String
    }

    /// 便宜上ここにベタ書きするが, 本来は外部データを元に生成.
    private let cellData: [CellData] = [
        CellData(cellClass: MyTableViewFooCell.self,
                 data: "Foo セルのデータ1."),
        CellData(cellClass: MyTableViewBarCell.self,
                 data: "Bar セルのデータ1."),
        CellData(cellClass: MyTableViewBarCell.self,
                 data: "Bar セルのデータ2."),
        CellData(cellClass: MyTableViewFooCell.self,
                 data: "Foo セルのデータ2."),
        CellData(cellClass: MyTableViewBazCell.self,
                 data: "Baz セルのデータ1."),
        CellData(cellClass: MyTableViewBarCell.self,
                 data: "Bar セルのデータ3."),
        CellData(cellClass: MyTableViewBarCell.self,
                 data: "Bar セルのデータ4."),
    ]

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let cell_classes: [MyTableViewCellProtocol.Type] = [
            MyTableViewFooCell.self,
            MyTableViewBarCell.self,
            MyTableViewBazCell.self ]
        for cell_class in cell_classes {
            tableView.register(
                UINib(nibName: cell_class.XIB_NAME,
                      bundle: nil),
                forCellReuseIdentifier: cell_class.IDENTIFIER)
        }
    }

    func tableView(_: UITableView, numberOfRowsInSection: Int) -> Int {
        return cellData.count
    }

    func tableView(_: UITableView,
                   heightForRowAt indexPath: IndexPath) -> CGFloat
    {
        return cellData[indexPath.row].cellClass.HEIGHT
    }

    func tableView(
        _ tableView: UITableView,
        cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        let cell_data = cellData[indexPath.row]
        let cell = tableView.dequeueReusableCell(
            withIdentifier: cell_data.cellClass.IDENTIFIER,
            for: indexPath)
        if let my_cell = cell_data.cellClass.cast(from: cell) {
            my_cell.setMyTableViewData(cell_data.data)
        }
        return cell
    }
}
```