/**
1.存储型属性的初始赋值
2.定制化构造过程
3.默认构造器
4.值类型的构造代理
5.类的继承和构造过程
6.通过闭包和函数来设置属性的默认值
OC不同,swift的构造器无需返回值
*/
//存储型属性的初始赋值
/**
为存储型属性设置默认值或者在构造器中为其赋值时,它们的值是被直接设置的,不会触发任何属性观察器
*/
//构造器
struct
var temperature: Double;
init() {
temperature = 32.0;
}
}
var f = Fahrenheit();
print(f.temperature);
.temperature = 10.0;
print(f.temperature);
//默认属性值
/**
可以在属性声明时设置默认值
如果一个属性总是使用同一个初始值,可以为其设置一个默认值。无论定义默认值还是在构造器中赋值,最终他们实现的效果是一样的,只不过默认值跟属性构造过程结合的更紧密。使用默认值能让你的造成器更简洁清晰,且能通过默认值自动推到出属性的类型,同时,也能充分利用默认构造器,构造器继承等特性
*/
struct
var temperature = 24.0;
}
var f2 = Fahrenheit2();
print(f2.temperature);
//定制化构造过程
/**
可以通过输入参数和可选属性类型来定制构造过程,也可以在构造过程中修改常量属性
*/
//构造参数
struct
var temperatureInCelsius: Double = 0.0;
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (fahrenheit - 32.0) / 1.8;
}
init(fromKelvin kelvin: Double) {
temperatureInCelsius = kelvin - 273.15;
}
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0);
print(boilingPointOfWater.temperatureInCelsius);
let freezingPointOfWater = Celsius(fromKelvin: 273.15);
print(freezingPointOfWater.temperatureInCelsius);
//内部和外部参数名
/**
跟函数和方法参数相同,构造参数也存在一个在构造器内部使用的参数名字和一个在调用构造器时使用的外部参数名字
swift会为每个构造器的参数自动生成一个跟内部名字相同的外部名
_来覆盖默认行为
*/
struct
var red = 0.0, green = 0.0, blue = 0.0;
init(red: Double, green: Double, blue: Double) {
self.red
self.green
self.blue
}
}
let magenta = Color(red: 1.0, green: 0.0, blue: 1.0);
//可选属性类型
/**
如果定制的类型包含一个逻辑上允许取值为空的存储型属性,不管是因为它无法在初始化时赋值,还是因为它可以在之后某个时间点可以赋值为空,都需要定义为可选类型
*/
class
var text: String;
var response: String?;
init(text: String) {
self.text
}
func
print(text);
}
}
let cheeseQuestion = SurveyQuestion(text: "do you like cheese?");
.ask();
print(cheeseQuestion.response);
cheeseQuestion.response = "Yes, i do like cheese."
print(cheeseQuestion.response!);
//构造过程中常量属性的修改
/**
只要在构造过程结束前常量的值能确定,可以在构造过程中的任意时间点修改常量属性的值
对某个类实例来说,它的常量属性只能在定义它的类的构造过程中修改,不能在子类中修改
*/
class
let text: String;
var response: String?;
init(text: String) {
self.text
}
func
print(self.text);
}
}
let beetsQuestion = SurveyQuestion2(text: "how about beets?")
.ask();
.response = "i also like beets.";
print(beetsQuestion.response!);
//默认构造器
class
var name: String?;
var quantity = 1;
var purchased = false;
}
var item = ShoppingListItem();
//结构体的逐一成员构造器
struct
var width = 0.0, height = 0.0;
}
let twoByTwo = Size(width: 2.0, height: 2.0);
//值类型的构造器代理
/**
构造器可以通过调用其他构造器来完成实例的部分构造过程。这一过程称为构造器代理,能减少多个构造器间的代码重复
构造器代理的实现规则和形式在值类型和类类型中有所不同。
值类型(结构体和枚举类型)不支持继承,所以构造器代理的过程相对简单,因为它只能代理任务给本身提供的其他构造器,类则不同,它可以继承自其它类,这意味着类有责任保证所有继承的存储型属性在构造时也能正确的初始化
self.init在自定义的构造器中引用其他的属于相同值类型的构造器,并且只能在构造器内部调用self.init
如果某个值类型定义了一个定制的构造器,将无法访问到默认构造器,可以防止在为值类型定义了一个更复杂的,完成了重要准备构造器之后,别人还是错误使用了那个自动生成的构造器
*/
struct
var width = 0.0, height = 0.0;
}
struct
var x = 0.0, y = 0.0;
}
struct
var origin = Point();
var size = Size2();
init() {};
init(origin: Point, size: Size2) {
self.origin
self.size
}
init(center: Point, size: Size2) {
let originX = center.x - size.width / 2;
let originY = center.y - size.height / 2;
self.init(origin: Point(x: originX, y: originY), size: size);
}
func
print("origin is \(self.origin.x, self.origin.y), and size is \(self.size.width, self.size.height)");
}
}
let basicRect = Rect();
basicRect.description();
let originRect = Rect(origin: Point(x: 2.0, y: 2.0), size: Size2(width: 5.0, height: 5.0));
originRect.description();
let centerRect = Rect(center: Point(x: 4.0, y: 4.0), size: Size2(width: 3.0, height: 3.0));
centerRect.description();
//类的继承和构造过程
/**
类里面的所有存储型属性,包括所有继承自父类的属性,都必须在构造过程中设置初始值
swift提供了两种类型的类构造器来确保所有类实例中存储属性都能获得初始值,分别是指定构造器和便利构造器
*/
//指定构造器和便利构造器
/**
指定构造器是类中最主要的构造器。一个指定构造器将初始化类中提供的所有属性,并根据父类链往上调用父类的构造器来实现父类的初始化
每一个类都必须拥有至少一个指定构造器,在某些情况下,许多通过继承了父类中的指定构造器而满足了这个条件
便利构造器是累中比较次要的,辅助性的构造器。可以定义便利构造器来调用同一个类中的指定构造器,并为其参数提供默认值。也可以定义便利构造器来创建一个特殊用途或特定输入发实例
在必要的时候为类提供便利构造器,能够节省更多开发时间并让类的构造过程更清晰明了
*/
//构造器链
/**
swift采用以下三条规则来限制构造器之间的代理调用
1.指定构造器必须调用其直接父类的指定构造器
2.便利构造器必须调用同一类中定义的其它构造器
3.便利构造器必须最终以调用一个指定构造器结束
即指定构造器必须总是向上代理,便利构造器必须总是横向代理
这些规则不会影响使用时,如何用类去创建实例,任何构造器都可以用来完整创建对应类的实例,这些规则只在实现类的定义时有影响
*/
//指定构造器语法
/**
init(parameters) {
statements
}
*/
//便利构造器语法
/**
需要在init关键字之前放置convenience关键字
convenience init(parameters) {
statements
}
*/
class
var name: String;
init(name: String) {
self.name
}
convenience init() {
self.init(name: "[Unnamed]");
}
}
let name1 = Food();
print(name1.name);
let nameMeat = Food(name: "Bacon");
print(nameMeat.name);
class RecipeIngredient: Food
var quantity: Int;
init(name: String, quantity: Int) {
self.quantity
super.init(name:name);
}
override convenience init(name: String) {
self.init(name: name, quantity: 1);
}
}
let oneMysteryItem = RecipeIngredient();
print(oneMysteryItem.name, oneMysteryItem.quantity);
let oneBacon = RecipeIngredient(name: "Bacon");
print(oneBacon.name, oneBacon.quantity);
let sixEggs = RecipeIngredient(name: "Eggs", quantity: 6);
print(sixEggs.name, sixEggs.quantity);
class ShoppingListItem2: RecipeIngredient
var purchased = false;
var description: String
var output = "\(quantity) * \(name.lowercaseString)";
purchased ? "Y" : "N";
return
}
}
var breakfastList = [ShoppingListItem2(), ShoppingListItem2(name: "Bacon"), ShoppingListItem2(name: "Eggs", quantity: 6)];
[0].name = "orange juice";
[0].purchased = true;
for item in breakfastList {
print(item.description);
}
//通过闭包和函数来设置属性的默认值
/**
如果某个存储型属性的默认值需要特别的定制或准备,你就可以使用闭包或全局函数来为其属性提供定制的默认值。每当某个属性所属的新类型实例创建时,对应的闭包或函数会被调用,而它们的返回值会当做默认值赋值给这个属性
这种类型的闭包或函数一般创建一个跟属性类型相同的临时变量,然后修改它的值以满足预期的初始状态,最后将这个临时变量的值作为属性的默认值进行返回
class SomeClass {
let someProperty: SomeType = {
}
在这个闭包中给 someProperty 创建一个默认值 // someValue 必须和 SomeType 类型相同
}()
}
swift需要立刻执行此闭包,如果忽略这对括号,相当于是将闭包本身作为值赋值给了属性,而不是将闭包的返回值赋值给属性
self属性,或者调用其它的实例方法
*/
struct
let boardColors: [Bool] = {
var temporaryBoard = [Bool]();
var isBlack = false;
for i in 1...10
for j in 1...10
append(isBlack);
isBlack = !isBlack;
}
isBlack = !isBlack;
}
return
}();
func squareIsBlackAtRow(row: Int, colum: Int) -> Bool
return boardColors[(row * 10) + colum];
}
}
let board = Checkerboard();
print(board.squareIsBlackAtRow(0, colum: 1));
print(board.squareIsBlackAtRow(9, colum: 9));