2016-12-11 69 views
1

我了解结构和类(和协议)如何在基本级别上工作。我有一个相当普遍的情况:结构或类似的子类

我需要具有运算符的通用值类型,这些运算符确实必须在赋值时进行复制。 这些类型具有复杂的结构,我希望能够通过子类化进行专门化,否则将会在任何地方复制代码,并且编程不好。

我试过协议和扩展,但后来因为协议不是通用的,我无法定义我想要的(通用)操作符。 如果我使用类,我不会复制作业。

今天的例子是矩阵和SquareMatrix下具有特定的方阵功能。有运营商和矩阵可以填充任何符合我的环协议。我试着用关联类型和扩展名来定义几乎所有的功能。

编辑:我真的想知道我应该编码。在矩阵情况下,我需要能够像其他任何方式一样传递方矩阵,所以子类化是唯一的选择?也许我错了。主要的问题是当我必须编写一个讨论内部价值的函数时,我必须知道泛型类型的参数来做任何有用的事情。例如,在定义加法时,我必须创建一个新的矩阵并声明它的泛型类型,但是从何时我只知道某个东西是(非泛型)协议开始,它是真正的类型是泛型的,但是尽管协议具有此关联类型,我无法把它弄出来。

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

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

+3

邮政编码你试过的是什么,实际的问题是什么。 – shallowThought

回答

8

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

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

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

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

由于这些原因,协议在Swift中扮演了很重要的角色,因为它们允许您在没有这些问题的情况下引入类似于继承的行为。

+0

谢谢。这就说得通了。我大多已经知道这一点。我的结构非常大,所以开销不是问题。 现在我想起这个场合,我只需要忍受类,因为我只需要一种类型来获得更多功能,但偶尔也会假装它是更简单的版本。叹息,今天没有价值类型。 我会修改我的问题,以“最佳政策是什么”为目标。 –

+1

@Richard Birkett声明协议矩阵,在扩展中添加默认行为,然后您的Struct SquareMatrix可以是具有额外行为的Matrix。值类型确认协议! – Irfan

+0

您不需要使用类,就像@Irfan建议的那样,只包含协议扩展中的所有功能,并让您的结构符合它。 – Alexander

0

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

另一方面,您需要Value Semantics,因此您可以使用Copy on Write方法。这将为你的类赋予语义价值(所以它们将像结构一样安全)。

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