1、类的指定构造器和便利构造器

类的构造器和结构体的构造器一样,是对自己类中定义的存储属性进行初始化。为了继承关系中把所有继承关系的类中的存储属性都保证初始化,Swift提供了2种不同类型的构造器来保证初始化行为。

1.1、指定构造器(Designated Initializers)

  • 指定构造器是类中主要构造器,每个类必须保证有一个以上的构造器(包括默认的指定构造器)。
  • 指定构造器负责初始化本身的存储属性,并且调用父类构造器,由父类来继续初始化过程。
  • 指定构造器可以通过继承而来。这部分介绍,在文章后面可以看到。
  • 指定构造器的语法跟普通的构造器语法一样,不加任何其他修饰:
1
2
3
init(parameters) {
statements
}

Read More

在今天的WWDC上,我们推出Swift 2.0。这个新的版本拥有更好的性能,带来了一个新的错误处理API和可用性检查的原始支持。使用Swift的平台APIs会变得更加自然,同时增强了苹果的SDKs。

开源

除了这些新的特性点以外,最大的消息是,苹果将在今年晚些时候将Swift开源。我们对此极其兴奋,期待在开源发布更近的时候,给大家更多的信息。在这里我们可以告诉大家以下信息:

  • Swift源代码将会基于某个OSI组织批准的开源协议进行开源
  • 将会允许并鼓励社区开发者贡献代码
  • 未来Swift将会重点支持 OS X、iOS和Linux三个平台
  • 源代码将包括Swift编译器和标准库
  • 我们相信在大家喜欢的平台上运行Swift将会令人兴奋

我们对开源`\Swift将会对整个行业带来的机会表示兴奋。内置安全性特性,加上出色的性能,Swift将有机会相对于C为基础的语言,极大的提高软件的开发效率。Swift包装了很多现代特性点,书写起来很愉快,而且我们相信Swift将会运用于很多地方。我们将一起拥有令人兴奋的前路。

Read More

因为Swift中涉及到的初始化的知识点比较多,所以学习笔记分2部分进行。第一部分学习基础的初始化知识,第二部分学习类中对初始化继承的知识。

1、Swift初始化过程概要

初始化过程对于一些面向对象的语言,如C++,Objective-C来说,是一个很重要的概念,不过使用和理解起来,会稍微有点难度,因为初始化过程,对于类的设计者来说,第一要区分默认构造器和自定义构造器的一些规则,第二是如果存在类继承的情况下,如何对父类进行初始化操作,也有一些规则。

对于Swift来讲,以上说的这些规则,在Swift官方文档当中,就花了很多篇幅来介绍初始化过程,尤其是类继承的初始化的一些规则。

这2部分学习笔记还是根据官方文档的顺序来展开,第一部分主要讲下如何对结构体,枚举和类进行初始化,Swift究竟提供了几种做法进行初始化过程,还有值类型(结构体,枚举)和类初始化的一些区别,另外由于值类型不能继承,所以一个值类型需要包含另外一个值类型时,进行的初始化操作就比较简单。这被称作值类型的构造器代理。而类继承下的初始化操作,我们放在第二部分进行介绍。

好了,说了那么多废话,还是进入正题。我们首先来看看,Swift的初始化有那些规则,总结如下,一些细节的学习,会在第二部分展开:

  • 初始化过程其实就是对存储属性进行赋值,Swift不允许在初始化过程结束后,还有存储属性存在不确定的值
  • Swift中使用init()作为构造器,且该定义不允许有返回值
  • 值类型和引用类型在一定条件都有默认的构造器,但是默认的构造器的定义会有不同
  • 也可以自定义构造器,但是必须使用init作为函数名,理论上可以定义很多构造器,只要语意上不冲突即可(参数定义不同)

Read More

近来对德州扑克比较感兴趣,于是想到52张牌,究竟会有多少种德州扑克结果组合。得到皇家同花顺的概率有多大呢?
得到皇家同花顺这个问题比较简单。皇家同花顺每个花色各一个,就只有4种情况会出现。我们只需要计算出所有组合C(52, 5)是多少就行了。
组合数的计算公式如下:

1
C(n, m) = n!/(m!*(n-m)!)

接下来我们使用错排法计算组合,首选我们把组合数公式做一下处理,便于大家理解错排发的原理。(注意:直接使用原始公式,阶乘计算到了xx就会越界,即使是64位,也到了xx会越界,错排法可以避免这个问题,但是如果本身组合数结果会越界,错排法也处理不了)

1
2
3
4
C(n, m) = n!/(m!*(n-m)!)
首先,把n!和(n-m)!做一下除法,得到n*(n-1)...*(n-m+1)
于是:
C(n, m) = n*(n-1)...*(n-m+1) / m*(m-1)*(m-2)*...1

Read More

1、Swift中继承的基本知识

  • 只能类可以进行继承,结构体和枚举无法进行继承
  • Swift没有一个统一的基类,Objective-C中有一个基类NSObject
  • 如果一个类没有继承其他类,就自动成为一个基类
  • 子类会继承父类所有的属性和方法
  • 可以使用final来阻止继承
  • Swift不支持多继承
  • 可以使用重写(Overriding)来重新定义子类的一些行为。
  • 可以进行重写的有:方法,属性,属性观测器,下标脚本

Read More

Objective-C里面,我们可以使用someArray[index]someDictionary[@"index"]ArrayDictionary的元素进行访问, 分别代替myArray.objectAtIndex(2)[someDictionary objectForKey:@"index"]。在Swift中,可以在类,结构体和枚举中使用subscripts来自定义下标。Swift中自定义下标的语法要求比较宽广,有以下一些特性:

  • 下标脚本的重载:可以同时定义多个subscripts,只要下标参数和返回值不一样即可
  • 下标脚本传入参数不支持in-out修饰和默认的参数值,支持外部参数名称
  • 类,结构体和枚举都支持下标脚本定义
  • 与计算属性的定义相同,使用getter和setter,同时支持定义只读下标脚本
  • 下标参数与普通方法参数默认定义情况有所区别,所有下标参数如果没有显式定义外部参数名称,Swift不会给下标参数默认加上外部参数名称。而实例中的方法是从第二个参数开始,会默认加上外部参数名称
  • 下标脚本允许返回Optional值

Read More

1、概要

方法(Method)就是绑定到特定类型(类,结构体,枚举都可以)的函数(Function)。在Objective-C中,只有类能定义方法,而在Swift中,类,结构体和枚举都可以定义方法。
方法也可以定义为类型方法,跟实例方法区分,类似于Swift中的类方法。

2、实例方法

定义实例方法的时候,主要注意Swift对参数命名的默认处理方式。为了兼容之前Cocoa Objective-C API的定义方式,Swift这种默认的参数命名方式发挥了作用。当你看到一个Objective-C API方法时,可以立即写出来,对应的Swift方法。这在后面的文章中专门来谈。
Swift中对方法的命名的默认规则有以下几条:

  • 第一个参数默认没有外部参数名称,也就是说,第一个参数是怎么定义的,就是保持本身的语意
  • 第二个参数开始,外部参数名称默认为局部参数名称,也就是说,只有局部参数名称的情况下,Swift自动加上跟局部参数名称一样的外部参数名称
  • 也可以改变这种默认行为,改变方式跟函数的用法相同。例如:显式地给第一个参数加上外部参数名称;或者对第二个参数加上_,显式地要求不提供外部参数名称

规则解释起来比较抽象,还是看具体的例子,好理解。。

Read More

原文地址:Memory Safety: Ensuring Values are Defined Before Use

在设计Swift的时候,一个主要的焦点是如何改进编程模型当中的内存安全。内存安全涉及到很多方面的问题,这篇文字开个头,只涉及到一个简单的知识点:如何确保变量在他们被用之前,用一个值进行初始化。

Swift的做法

开发者确认在任何代码访问变量之前,变量有一个已经准备好的有效值,这种情况下,变量将被认为是”安全”的。编程语言采用几种不同的做法来做到这样的安全性。比如C语言,就把这个负担全部交给程序员,实现这种安全编码技术,这是一个很强大的做法,但是充满了风险。C++和Objective-C使用一些强制性规则来改进C语言的做法,还有一些语言采取了更加极端的做法,需要保证在定义的时候就做初始化。

Read More

1、概要

属性用来描述类,结构体或者枚举里面的值。属性分为存储属性和计算属性,存储属性存储类中常量和变量的值,而计算属性计算常量或者变量的值。存储属性只能放到类和结构体当中。计算属性可以放到类,结构体和枚举当中。
存储属性类似于Objective-C中的成员变量。
计算属性就是Objective-C中的gettersetter器。

2、存储属性

2.1、基础知识

在类和结构体中定义存储属性,枚举中不支持。可以使用var和let修饰存储属性,分别代表变量存储属性和常量存储属性(赋值后不可变更)。两种存储属性都可以在定义时候赋值,并且常量存储属性可以在类和结构体的构造器中赋值。使用The Swift Language Programming的例子,然后加了一些自己的理解和说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
struct FixedLengthRange {
var firstValue: Int //变量,随时可以修改
let length: Int //常量,初始化后不能修改
}
//使用逐一成员构造器对成员进行初始化
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
rangeOfThreeItems.firstValue = 6
//报错,不能对结构体常量进行赋值
rangeOfThreeItems.length = 4
//定义常量实例,结构体里面所有的存储属性变成常量,不能修改
let rangeOfFourItems = FixedLengthRange(firstValue: 1, length: 4)
//rangeOfFourItems.firstValue = 10 --错误,不能修改
class FixedLengthRangeClass
{
var firstValue: Int = 0
let length: Int = 1
}
let rangeClass = FixedLengthRangeClass()
rangeClass.firstValue = 2 --可以修改
rangeClass.length = 2 --不能修改,因为定义为常量
//原因是结构体是值类型的,定义一个常量结构体实例,
//对应的存储属性都变成了常量。而类是引用类型的,
//只是实例是常量,里面的存储属性跟本身定义一样。

Read More

原文地址:点击连接

跟大多数编程语言一样,Swift允许一个类重写(override)其父类的方法和属性。这意味着,程序会在运行时去推断出调用的方法或属性,然后进行间接的调用或者访问。这种技术,我们称之为动态分配(dynamic dispatch)。这增强了语言的表达能力,但同时会为每一个运行时的间接访问增加一个固定的开销.从性能角度来讲,使用这种方式的代码通常是不受欢迎的。这篇博客会提供3种方式,通过消除这种动态特性来增强性能:final关键字,private关键字以及全模块优化(Whole Module Optimization)

Read More