方法如何访问调用者的属性?

时间:2017-06-23 13:21:55

标签: swift struct nested

我有一个包含2个属性的结构,它们相互依赖。可以通过将它们中的任何一个作为参数传递来创建实例,然后初始化器将调用函数来计算相应的另一个。此计算需要另一个变量的值,该变量在我的操场顶部声明为全局变量:

var grid: Int = 8

struct myStruct {
    var valueAsTuple: (Int,Int,Int)
    var valueAsInt: Int

    init(_ value: (Int,Int,Int)) {
        self.valueAsTuple = value
        self.valueAsInt = 0
        self.valueAsInt = getIntFromTuple(value)
    }

    init(singleInt: Int) {
        self.valueAsTuple = (0,0,0)
        self.valueAsInt = singleInt
        self.valueAsTuple = getTupleFromInt(singleInt)
    }

    func getIntFromTuple(tuple: (Int,Int,Int)) -> Int {

        // do some math using the global grid variable

        return result
    }

    func getTupleFromInt(int: Int) -> (Int,Int,Int) {

        // do some math using the global grid variable

        return result
    }
}

这在操场上很好用。但是,最后myStruct永远不会被用作单个实例,但是另一个struct将保存myStructs数组。这个封装结构将具有属性“grid”,并且在计算myStruct的属性时应该使用此属性。

可以创建封装属性的多个实例,每个实例都具有不同的“网格”值,因此在外部结构的一个实例中创建的myStruct实例将为相应的其他实例获得不同的结果属性而不是在不同实例中创建的属性。

我是面向对象编程的新手,所以我还在学习如何组织代码以实现我的特定目标。

我试图将myStruct嵌套到外部结构中,但是我得到错误:“实例成员'grid'不能用于'myStruct'类型。

将grid var更改为static会使嵌套结构看到它,但这样就无法为外部结构的每个实例赋予不同的网格值。

因此,简而言之,对于必须使用其周围范围属性的对象进行编码的快捷方式是什么?

编辑:

我试着给出一个更清晰的例子:

想象一下,你有许多鸡蛋,你想把它们存放在盒子里。蛋可以具有绝对数(m),它可以是框(o)中的第(n)个蛋。您可以告诉初始化程序将鸡蛋存储在绝对位置(m)或特定盒子的特定位置。

现在有一些盒子可以容纳6个鸡蛋,这样可以容纳10个鸡蛋。当然,我可以在每个鸡蛋初始化时传递盒子容量('网格'值),但我要找的是一个让初始化程序知道我想要追加的数组的框大小的简便方法是:

shelfWithSmallBoxes.boxesArray.append(21)
// now there is an egg at absolute position 21
print(shelfWithSmallBoxes.boxesArray.last.asTuple

shelfWithLargeBoxes.boxesArray.append(21)
// also here is an egg at absolute position 21
print(shelfWithLargeBoxes.boxesArray.last.asTuple

the first result should be (4,3), as the egg would be placed in the 4th box at position 3, the second result should be (3,1)

我认为,这不是一个太奇特的问题,我只是太新手,不知道什么方法是最佳实践。

2 个答案:

答案 0 :(得分:0)

grid作为初始化程序的一部分传递。这是一种非常常见的模式:

init(_ value: (Int,Int,Int), in grid: Grid)
init(singleInt: Int, in grid: Grid)

没有规则说您传递给init的内容必须是目标的属性。

在你的鸡蛋"例如,我认为混淆是没有理由(至少在你的例子中)鸡蛋知道它们在哪里。这里有趣的类型是集合(框或网格)。关于自身内部的位置应该很聪明。鸡蛋对于地点应该是愚蠢的。问题似乎是你试图让你的盒子类型为Array,但这不是正确的工具;它对这个问题不够聪明。创建Box类型(或Grid类型)。它可能包含Array作为后备存储,但这并不重要。如果鸡蛋没有内部结构,可能更容易将它们保持为[Int: Egg](或者甚至只是作为Set的索引。)

这里的关键是,事情通常不应该将自己插入集合或在集合内部进行自我管理。应将事物传递给要插入和管理的集合。

答案 1 :(得分:0)

一种可能的解决方案是将valueAsTuplevalue之间的计算移动到父结构。 看起来您正在存储网格索引,并且计算取决于网格大小。

这与Swift中的现有Collection API类似,其中集合使用以下函数对其索引进行数学计算:

collection.index(after: anIndex)
collection.distance(from: anIndex, to: anotherIndex)

其他可能性是:

  1. grid。{/ li>中包含MyStruct变量作为实例变量
  2. MyStruct中存储对父类型的引用(仅在父类型为类时才有效)
  3. grid存储在父结构中,并将其传递给需要它的每个函数调用。