Swift 中的嵌套类型

Nested types in Swift

提问人:111 提问时间:8/15/2023 最后编辑:111 更新时间:8/15/2023 访问量:39

问:

我有带有单元格的 UICollectionView:图像、文本或图像+文本。

class ParentCell: UICollectionViewCell {
    class ImageCell: ParentCell {
        class TextCell: ImageCell { }
    }
    class TextCell: ParentCell { }
}
func createTextCellId(classPrefix: ParentCell.Type) -> String {
    return String(reflecting: classPrefix.TextCell)
}

为什么 Swift 会删除嵌套类型?

// CORRECT: ParentCell.TextCell
createTextCellId(classPrefix: ParentCell.self)

// INCORRECT: ParentCell.TextCell
createTextCellId(classPrefix: ParentCell.ImageCell.self)

其他功能不起作用:

func createTextCellId<ParentCellType: ParentCell>(classPrefix: ParentCellType.Type) -> String {
    return String(reflecting: classPrefix.TextCell)
}
Swift 泛型 类层次结构 套类型

评论


答:

3赞 Sweeper 8/15/2023 #1

这不是 Swift 的工作方式。 在您的代码中,将始终表示 中声明的 ,而不是 中声明的。classPrefix.TextCellTextCellParentCellImageCell

要对类型进行这种动态解析,您需要一个协议:

protocol TextCellProviding: UICollectionViewCell {
    associatedtype TextCell: UICollectionViewCell
}

然后你可以做:

func createTextCellId<Cell: TextCellProviding>(classPrefix: Cell.Type) -> String {
    return String(reflecting: classPrefix.TextCell)
}

那么你的设计可以是:

class ParentCell: UICollectionViewCell {
    
}

class ImageCell: ParentCell, TextCellProviding {
    typealias TextCell = ImageAndTextCell
}

// You can nest ImageAndTextCell in ImageCell if you want, but I think it is less readable that way
// Perhaps LabelledImageCell could be a better name? Or ImageCell.Labelled
class ImageAndTextCell: ImageCell { }

class TextOnlyCell: ParentCell, TextCellProviding {
    typealias TextCell = TextOnlyCell
}

请注意,不能符合 。否则,同样的问题再次发生 - 即 决定它的所有子类应该是什么,而它的子类不能改变它。ParentCellTextCellProvidingParentCellTextCell

例:

createTextCellId(classPrefix: TextOnlyCell.self) // TextOnlyCell
createTextCellId(classPrefix: ImageCell.self) // ImageAndTextCell

还要考虑你是否真的需要.如果所有常用功能都可以(并且有意义)通过扩展来实现,请考虑这样做。ParentCellTextCellProviding