swift 3.0 结构体和类 (无脑码农 VS 技术逼) 的不同理解一

本月在IOS培训班刚毕业,就出了swift 3.0 .好吧让我这水平差的自学吧!

咱也"高大上"一回,看看官方文档,英文看不懂啊!官方文档地址:https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-ID82

咱有谷歌翻译啊!我的理想就是先成为一名码农嘛!

在结构体部分看了快2小时终于明白了,明白什么呢!

技术逼害人啊~


先来看苹果官方文档:            (码农们可以直接看最后图片部分)

(谷歌翻译的,经过多年锻炼我已经能看懂各种中文了!)

类和结构

结构是通用的,即成为你的程序的代码的积木柔性结构。您可以定义属性和方法,通过使用完全相同的语法为常量,变量和函数将功能添加到您的类和结构。

不像其他的编程语言,斯威夫特不要求你创建单独的接口和实现文件自定义类和结构。在斯威夫特,你定义一个类或单个文件的结构,外部接口到类或结构的其他代码使用的是自动提供。

注意

一个实例是传统上已知的作为对象。然而,斯威夫特类和结构在功能上比其他语言更接近,而很多本章介绍了可以应用到的实例功能,无论是类或结构类型。正因为如此,更普通的术语实例被使用。

比较类和结构

类和结构斯威夫特有许多共同的东西。两者都可以:

定义属性来存储值

限定的方法来提供功能

定义标用标语法,提供访问其值

定义初始化设置它们的初始状态

延伸拓展其功能超出了默认的实现

顺应协议来提供某一种标准功能

欲了解更多信息,请参见属性,方法,下标,初始化,扩展和协议。

类具有结构不附加的功能:

继承允许一个类继承的另一个特点。

类型转换可以检查并在运行时解释一个类实例的类型。

Deinitializers使类的一个实例,以释放它已经分配的任何资源。

引用计数允许多个参考一类实例。

欲了解更多信息,请参见继承,类型转换,反初始化,并自动引用计数。

注意

当他们在你的代码通过周围,也不要使用引用计数的结构总是被复制。

定义语法

类和结构有一个类似的定义语法。你介绍类的class关键字和结构的struct关键字。无论放置一对大括号内的所有定义:

classSomeClass{

// class definition goes here

}

structSomeStructure{

// structure definition goes here

}

注意

当你定义一个新的类或结构,您可以有效地定义了一个全新的雨燕。给出类型UpperCamelCase名称(如SomeClass和SomeStructure这里)来匹配标准斯威夫特类型的资本(如String,Int和Bool)。相反,总是给的属性和方法lowerCamelCase的名称(如frameRate和incrementCount),从类型名称区分。

这里有一个结构定义和类定义的例子:

structResolution{

varwidth=0

varheight=0

}

classVideoMode{

varresolution=Resolution()

varinterlaced=false

varframeRate=0.0

varname:String?

}

上面的例子中定义了一个新的结构叫做Resolution,描述一个基于像素的显示分辨率。这种结构叫了两个存储性能width和height。存储属性是常量或者被捆绑起来,作为类或结构的一部分存储的变量。这两个属性被推断为类型Int将它们设置为初始整数值0。

上面还的例子定义了一个名为新类VideoMode,来描述视频显示一个特定的视频模式。这个类有四个变量存储性能。第一,resolution被初始化一个新的Resolution结构实例,其中推断的属性类型Resolution。对于其他三个属性,新VideoMode实例将与被初始化interlaced设定false(意为“非隔行扫描视频”)的再现帧速率0.0,和一个可选String称为值name。在name属性自动给出的缺省值nil,或“无name值”,是因为它是一个可选的类型。

种类及结构实例

该Resolution结构定义和VideoMode类的定义只说明什么Resolution或者VideoMode看起来像。他们自己不描述具体的分辨率或视频模式。要做到这一点,你需要创建的结构或类的一个实例。

创建实例的语法为结构和类非常相似:

letsomeResolution=Resolution()

letsomeVideoMode=VideoMode()

结构和类都使用了新的实例初始化程序语法。初始化语法最简单的形式使用类或结构后跟空括号,如的类型名称Resolution()或VideoMode()。这将创建类或结构的新实例,与任何属性初始化为它们的默认值。类和结构初始化中更详细地描述初始化。

访问属性

您可以访问使用实例的属性点语法。在点语法,你实例名称后立即写入属性名,用句点(分离.),没有任何空格:

print("The width of someResolution is\(someResolution.width)")

// Prints "The width of someResolution is 0"

在这个例子中,someResolution.width是指width的属性someResolution,并返回其默认初始值0。

您可以深入到子属性,如width在属性resolution的属性VideoMode:

print("The width of someVideoMode is\(someVideoMode.resolution.width)")

// Prints "The width of someVideoMode is 0"

您还可以使用点语法到一个新的值赋给变量属性:

someVideoMode.resolution.width=1280

print("The width of someVideoMode is now\(someVideoMode.resolution.width)")

// Prints "The width of someVideoMode is now 1280"

注意

不同的Objective-C,斯威夫特使您能够直接设置的结构属性的子属性。在上面的例子,把width该财产resolution的财产someVideoMode被直接设置,没有你需要将整个设置resolution属性为一个新值。

按成员初始化器的结构类型

所有的结构具有自动生成的成员逐一初始化,您可以用它来初始化新的结构实例的成员属性。新实例的属性的初始值可以被传递到由名成员逐一初始化:

letvga=Resolution(width:640,height:480)

不同的结构,类实例没有收到默认成员逐一初始化。初始化中更详细地描述初始化。

结构和枚举是值类型

一个值类型是一个类型,其值被复制时,它被分配给一个变量或常数,或当它被传递给函数。

你已经使用值类型广泛的整个前几章实际上是。事实上,所有斯威夫特 - 整数基本类型,浮点数,布尔值,字符串,数组和字典,是值类型,并作为幕后结构实现的。

所有的结构和枚举是斯威夫特值类型。这意味着用户可创建和任何结构和枚举实例的任何值类型它们作为属性,是当他们在你的代码中传来传去始终复制。

考虑下面这个例子,它使用了Resolution前面例子中的结构:

lethd=Resolution(width:1920,height:1080)

varcinema=hd

这个例子声明了一个名为常量hd并将其设置为一个Resolution与(全高清视频的宽度和高度初始化实例,1920通过像素宽1080像素高)。

然后,它声明了一个变量cinema并将其设置为当前值hd。因为Resolution是一个结构,一个复制现有实例而成,而这个新的拷贝被分配到cinema。即使hd与cinema现在具有相同的宽度和高度,它们是在幕后两个完全不同的实例。

接下来,width财产cinema被修订为稍微增多的2K标准用于数字电影放映(宽度2048像素宽,1080像素高):

cinema.width=2048

检查width的属性cinema表明,它确实已经更改为2048:

print("cinema is now\(cinema.width)pixels wide")

// Prints "cinema is now 2048 pixels wide"

然而,width与原始属性hd实例仍具有的旧值1920:

print("hd is still\(hd.width)pixels wide")

// Prints "hd is still 1920 pixels wide"

当cinema被赋予的当前值hd,该存储在hd被复制到新的cinema实例。最终的结果是两个完全独立的情况下,这正好包含相同的数值。因为它们是独立的情况下,设置的宽度cinema以2048不影响存储在宽度hd。

同样的行为适用于枚举:

enumCompassPoint{

casenorth,south,east,west

}

varcurrentDirection=CompassPoint.west

letrememberedDirection=currentDirection

currentDirection= .east

ifrememberedDirection== .west{

print("The remembered direction is still .west")

}

// Prints "The remembered direction is still .west"

当rememberedDirection被分配的值currentDirection,它实际上是设置为该值的副本。改变的值currentDirection此后不会影响被存储在所述原始值的副本rememberedDirection。

类引用类型

不像值类型,引用类型当它们被分配给一个变量或常数,或当它们被传递给函数复制。而不是一个拷贝,为相同的现有实例的引用来替代。

下面是一个例子,使用VideoMode上面定义的类:

lettenEighty=VideoMode()

tenEighty.resolution=hd

tenEighty.interlaced=true

tenEighty.name="1080i"

tenEighty.frameRate=25.0

这个例子声明一个称为新的常数tenEighty,并将它以引用的新实例VideoMode的类。视频模式分配的高清分辨率的副本,1920通过1080从之前。它被设置为交错,并且被赋予的名称"1080i"。最后,它被设置为帧速率25.0每秒帧。

接着,tenEighty被分配给一个新的常数,称为alsoTenEighty和的帧速率alsoTenEighty被修改:

letalsoTenEighty=tenEighty

alsoTenEighty.frameRate=30.0

由于类是引用类型,tenEighty而alsoTenEighty实际上指的是同一个VideoMode实例。有效地,它们只是两个用于同单个实例不同的名字。

检查frameRate的财产tenEighty,它可以正确地报告的新的帧速率显示30.0从底层的VideoMode实例:

print("The frameRate property of tenEighty is now\(tenEighty.frameRate)")

// Prints "The frameRate property of tenEighty is now 30.0"

请注意,tenEighty并alsoTenEighty声明为常量,而不是变量。但是,你仍然可以改变tenEighty.frameRate和alsoTenEighty.frameRate由于价值观tenEighty和alsoTenEighty常量本身并不真正改变,tenEighty而alsoTenEighty本身并没有“商店”的VideoMode实例相反,他们都到VideoMode幕后实例。它是frameRate在底层的属性VideoMode被改变,为了使恒定引用不值VideoMode。

运营商身份

因为类是参考的类型,它有可能为多个常量和变量来指幕后一类的相同的单一实例。(同样是不适合的结构和枚举真实的,因为当他们被分配到固定或可变他们总是复制或传递给函数)。

如果两个常量或变量指的正是一个类的同一个实例它有时是有用的找出来。为了实现这一目标,雨燕提供了两个身份运营商:

等同于(===)

不相同(!==)

使用这些运算符检查两个常量或变量是否指的是同一个实例:

iftenEighty===alsoTenEighty{

print("tenEighty and alsoTenEighty refer to the same VideoMode instance.")

}

// Prints "tenEighty and alsoTenEighty refer to the same VideoMode instance."

请注意,“相同”(代表由三个等号,或===)并不意味着同样的事情为“等于”(由两个代表等号,或==):

“等同于”是指两个常数或类类型的的变量是指完全相同的类的实例。

“等于”是指两个实例被认为是值“等于”或“等价物”,对于“平等”的一些适当的意义,由该类型的设计师定义。

当你定义自己的自定义类和结构,它是你的责任,决定为两个实例是“平等”什么资格。定义你自己的实现的过程“等于”和“不等于”运营商在描述对等运营商。

指针

如果你有C,C ++或Objective-C的经验,你可能知道,这些语言使用指针指到的地址在内存中。这是指一些参考类型的实例迅速常量或变量是类似于C的指针,而不是直接指向内存中的地址,并且不需要你写一个星号(*),以表明您创建参考。相反,这些参考文献中定义像夫特任何其它固定或可变。

选择类和结构之间

您可以同时使用类和结构来定义自定义数据类型作为您的程序代码积木使用。

然而,结构实例总是被传递价值,和类实例总是过去了参考。这意味着它们适合于不同类型的任务。当你认为你需要一个项目中的数据结构和功能,决定每一个数据结构是否应该被定义为类或结构。

作为一般原则,考虑创建一个结构,当一个或多个条件适用:

结构的主要目的是封装几个比较简单的数据值。

这是合理的预期,封装的值将被复制,而不是当你分配或绕过该结构的一个实例引用。

由结构存储的任何属性本身的值类型,这也将被预期要复制的,而不是被引用。

该结构不需要从其他现有类型继承属性或行为。

良好候选结构的实例包括:

几何形状的尺寸,或者包封width属性和height属性,两个类型的Double。

一种方法来指代范围内的系列中,也许一个封装start属性和length特性,既类型Int。

在三维坐标系中,A点也许封装x,y和z特性,每种类型的Double。

在其他情况下,定义一个类,并创建一个类的实例来进行管理,并通过引用传递。在实践中,这意味着大多数自定义数据结构应该是类,而不是结构。

技术逼写了那么多代码,一会这个值变了,一会这个值又没变,像变戏法一样... ...

===========================================================================

无脑码农看这里  :

之前百度了各种文章,各种举例,代码,论证,最后无奈看了官方文档,2个小时后我终于理解了!

如图:

swift 3.0 结构体和类 (无脑码农 VS 技术逼) 的不同理解一_第1张图片
ZN 类的实例化之间存在地址传递的关系,结构体的实例化之间是值传递的关系!

其实就是两句话:

1 类的每个实例化之间存在地址传递的关系,(上边例子地址同为:0x0000610000038140)在使用类时需要考虑继承关系.

2 结构体的每个实例化之间是值传递的关系,赋给什么值,就是什么值.是相对独立的关系.


最后总结:

      swift 3.0中 结构体比以前范围更强大了,可以和类一样有方法,扩展,属性变异修饰还增加了下标法.但是重要的,结构体强调了每一个实例化之间独立的存在,互不干涉的特点.

      考虑到新增的上述特性,种种迹象表明,结构体是苹果主要针对未来的Web服务器开发,科学计算,人工智能,等数值计算方面,量身定做的一个特性类型.喜欢这个领域的码农们可以在结构体章节进行深入的研究.他对你来说比Class类型更加重要.

       如果只在IOS领域开发大众化的APP方面,那结构体的新特性和我们的关系并不是很大.但是长远来看,swift这门语言已经具备了目前所有语言的优点,就语言自身来说超越了PHP,Python,JAVA当前主流的语言,也包括Lisp函数式的很多优点.尽管如此swift为了兼容OC也还是做出了很多妥协.因此我们完全有理由认真学习swift的每一项特性,我完全相信,如同苹果说的那样,在未来20年之内swift将会是非常主流的语言!

你可能感兴趣的:(swift 3.0 结构体和类 (无脑码农 VS 技术逼) 的不同理解一)