子类化结构或类似

时间:2016-12-11 19:09:58

标签: swift generics struct subclassing

我理解结构和类(和协议)如何在基本级别上工作。我有一个相当常见的情况:

我需要使用操作符的泛型值类型,这些操作符必须在赋值时复制。 这些类型具有复杂的结构,我希望能够通过子类化来专门化,否则会在任何地方复制代码,这将是糟糕的编程。

我已经尝试过协议和扩展但是因为协议不是通用的,我无法定义我想要的(通用)运算符。 如果我使用课程,我将不会复制作业。

今天的例子是我有Matrix和SquareMatrix,具有特定的方矩阵功能。有些运算符和矩阵可以由符合我的环协议的任何东西填充。我尝试在协议中定义几乎所有具有关联类型和扩展名的功能。

编辑:我真的很想知道我应该编码什么。在矩阵情况下,我需要能够像任何其他矩阵一样传递方矩阵,所以子类化是唯一的选择吗?也许我错了。主要问题是当我必须编写一个讨论内部值的函数时,我必须知道泛型类型参数来做任何有用的事情。例如,当定义添加时,我必须创建一个新的矩阵并声明它的泛型类型,但是当我只知道某个(非泛型)协议时,我从哪里得到它 - 它的真实类型是通用的但是尽管协议具有这种关联类型,我无法解决它。

解决方案感谢alexander momchliov。基本上需要更多的工作来将代码完全移动到协议扩展中,并对所有相关类型使用“Self”。在扩展中,编译器对通用类型的内容感到满意。

代码是私密的,很抱歉,我无法在此问题中粘贴任何代码。感谢您的耐心和帮助。

2 个答案:

答案 0 :(得分:11)

结构继承/多态性至少有两个原因是不可能的(我能想到)。

  1. 结构按值存储和移动。这需要编译器在编译时知道结构的确切大小,以便知道在结构实例启动后要复制多少字节。

    假设有一个结构A和一个继承自B的结构A。每当编译器看到A类型的变量时,它无法确定运行时类型是否真的是A,或者是否使用了B。如果在B没有的新存储属性上添加了A,那么B的大小将与A不同(更大)。编译器将无法确定运行时类型以及这些结构的大小。

  2. 多态性需要一个功能表。函数表将存储为结构类型的静态成员。但是要访问此静态成员,每个结构实例都需要一个实例成员来编码实例的类型。这通常被称为" isa"指针(如,此实例 A类型)。对于每个实例,这将是8字节的开销(在64位系统上)。考虑IntBoolDouble和许多其他常见类型都是作为结构实现的,这将是不可接受的开销量。试想一下,Bool是一个字节值,需要8个字节的开销。那效率是11%!

  3. 由于这些原因,协议在Swift中发挥了重要作用,因为它们允许您引入类似继承的行为,而不会出现这些问题。

答案 1 :(得分:0)

首先,在swift中,如果您使用associatedtype,协议可以是通用的。

总而言之,您需要Value Semantics,因此您可以使用Copy on Write方法。这将为您的类提供语义值(因此它们将像结构一样安全)。

这两种方式都可以用来解决你的问题。