Swift5.0和Swift3.0
Swift 是一种支持多编程范式和编译式的开源编程语言,苹果于2014年WWDC(苹果开发者大会)发布,用于开发 iOS,OS X 和 watchOS 应用程序。
Swift 结合了 C 和 Objective-C 的优点并且不受 C 兼容性的限制。
Swift 在 Mac OS 和 iOS 平台可以和 Object-C 使用相同的运行环境。
2015年6月8日,苹果于WWDC 2015上宣布,Swift将开放源代码,包括编译器和标准库。
--------------------------------------------目录---------------------------------
Swift 教程
Swift 环境搭建
Swift 基本语法
Swift 数据类型
Swift 变量
Swift 可选类型
Swift 常量
Swift 字面量
Swift 运算符
Swift 条件语句Swift 循环
Swift 字符串
Swift 字符
Swift 数组
Swift 字典
Swift 函数
Swift 闭包
Swift 枚举
Swift 结构体
Swift 类
Swift 属性
Swift 方法
Swift 下标脚本
Swift 继承
Swift 构造过程
Swift 析构过程
Swift 可选链
Swift 自动引用计数Swift 类型转换
Swift 扩展
Swift 协议
Swift 泛型
Swift 访问控制
--------------------------------------------目录结束---------------------------------
import UIKit
//1. swift标记
var str = "play ground"
print(str)
print("test1!")
print(
"test1!"
)
//2.swift注释
// 这是单行注释
/*
这是多条注释
*/
//3.分号
var str1 = "hello"; print(str);
//4.标识符
let `class` = "roolunm";print(`class`)
//5.swift 空格
let a = 1 + 2; print(a)
//6.swift字面量
42
3.1415
"hello,world"
true
//7.打印输出
print("hello runloob")
for n in 1...10 {
print(n)
}
let theinput = readLine()
//---------------------------------------------------------------------------------------------------
//8.swift 数据类型
//swift提供了非常丰富的数据类型,一下列出常用的内置类型
//整型 Int Uint
//浮点型 Float Double
//布尔类型 Bool
//字符串类型 String
//字符类型 Character
//可选类型 Optional
//9. 类型别名:类型别名对当前的类型定义了另一个名字,类型别名通过使用 typealias 关键字来定义。语法格式如下:
typealias newname = Int;
var b:newname = 20;
print(b)
//10.类型安全:由于 Swift 是类型安全的,所以它会在编译你的代码时进行类型检查(type checks),并把不匹配的类型标记为错误。这可以让你在开发的时候尽早发现并修复错误。
/*
var varA = 42
varA = "helloword"
print(varA)
*/
//11.0.类型判断:当你要处理不同类型的值时,类型检查可以帮你避免错误。然而,这并不是说你每次声明常量和变量的时候都需要显式指定类型。如果你没有显式指定类型,Swift 会使用类型推断(type inference)来选择合适的类型。
//例如,如果你给一个新常量赋值42并且没有标明类型,Swift 可以推断出常量类型是Int,因为你给它赋的初始值看起来像一个整数:
let pi = 3.1415926
let pi1:Float = 3.1415926
let pi2 = 3 + 3.1415926
//---------------------------------------------------------------------------------------------------
//12.swift变量:变量是一种使用方便的占位符,用于引用计算机内存地址。
//13.swift变量的申明
// var varliable = <initValue>
var varB = 42
print(varB)
var varB1:String = "hello"
print(varB1)
//14.变量命名:
/*
变量名可以由字母,数字和下划线组成。
变量名需要以字母或下划线开始。
Swift 是一个区分大小写的语言,所以字母大写与小写是不一样的。
变量名也可以使用简单的 Unicode 字符,如下实例:
*/
var _var = "hello,swift"
var 你好 = "变量名尽然是汉字,你也是个人才啊"
print(你好)
//15.变量输出
var bname = "菜鸟教程"
var site = "https://www.baidu.com"
print(bname)
print("\(site)")
print("\(bname)的地址是\(site)")
//---------------------------------------------------------------------------------------------------
//16.swift可选类型(Options)
/*
Swift 的可选(Optional)类型,用于处理值缺失的情况。可选表示"那儿有一个值,并且它等于 x "或者"那儿没有值"。
Swfit语言定义后缀?作为命名类型Optional的简写,换句话说,以下两种声明是相等的:
*/
var optionInteger:Int?
var optionInteger1:Optional<Int>
//如果一个可选类型的实例包含一个值,你可以用后缀操作符 !来访问这个值,如下所示:
var optionalInter1 = 42
print(optionalInter1)
var mystring:String? = nil
mystring = "123456"
if mystring != nil {
print(mystring)
}else{
print("nil")
}
//17.强制解析:当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个感叹号(!)来获取值。这个感叹号表示"我知道这个可选有值,请使用它。"这被称为可选值的强制解析(forced unwrapping)。
if mystring != nil {
print(mystring!)
}else{
print("nil")
}
//18.自动解析:你可以在声明可选变量时使用感叹号(!)替换问号(?)。这样可选变量在使用时就不需要再加一个感叹号(!)来获取值,它会自动解析。
var mystring1:String!
mystring1 = "wwwwww"
if mystring1 != nil {
print(mystring1)
}else{
print("nil")
}
//19.可选绑定:
var myString2:String?
myString2 = "Hello, Swift!"
if let yourString = myString2 {
print("你的字符串值为 - \(yourString)")
}else{
print("你的字符串没有值")
}
//---------------------------------------------------------------------------------------------------
//20.常量
/**
常量一旦设定,在程序运行时就无法改变其值。
常量可以是任何的数据类型如:整型常量,浮点型常量,字符常量或字符串常量。同样也有枚举类型的常量:
常量类似于变量,区别在于常量的值一旦设定就不能改变,而变量的值可以随意更改。
*/
//格式: let 常量名 = 初始值
let constA = 42
print(constA)
let constB:Float = 3.14567
print(constB)
//21.常量命名
/**
常量的命名可以由字母,数字和下划线组成。
常量需要以字母或下划线开始。
Swift 是一个区分大小写的语言,所以字母大写与小写是不一样的。
常量名也可以使用简单的 Unicode 字符,如下实例:
*/
//22.常量输出
let name1 = "菜鸟教程"
let site1 = "http://www.runoob.com"
print("\(name1)的官网地址为:\(site1)")
//---------------------------------------------------------------------------------------------------
//23.字面量
//23.1整型字面量
let aaa = 17
let bbb = 0b0001
let ccc = 0o21
let ddd = 0x11
//23.2浮点型字面量
let AAA = 12.785
let BBB = 1.223e1
let CCC = 0xC.3p0
//23.3字符串字面量
let stringL = "Hello\tWorld\n\n菜鸟教程官网:\'http://www.runoob.com\'"
print(stringL)
//23.4布尔类型字面量
let bo = true;
print(bo)
//---------------------------------------------------------------------------------------------------
//24.Swift 运算符
/**
算术运算符
比较运算符
逻辑运算符
位运算符
赋值运算符
区间运算符
其他运算符
*/
//24.1算术运算符
var C1 = 10
var C2 = 20
print("c1+c2的结果为\(C1 + C2)")
print("c1+c2的结果为\(C1 + C2)")
print("c1-c2的结果为\(C1 - C2)")
print("c1*c2的结果为\(C1 * C2)")
print("c1/c2的结果为\(C1 / C2)")
print("c1%c2的结果为\(C1 % C2)")
C1+=1
print("c1+=1的结果为\(C1)")
C2-=1
print("c1-=的结果为\(C2)")
//24.2比较运算符
var A = 10
var B = 20
print("A == B 结果为:\(A == B)")
print("A != B 结果为:\(A != B)")
print("A > B 结果为:\(A > B)")
print("A < B 结果为:\(A < B)")
print("A >= B 结果为:\(A >= B)")
print("A <= B 结果为:\(A <= B)")
//24.3逻辑运算符
var A1 = true
var B1 = false
print("A && B 结果为:\(A1 && B1)")
print("A || B 结果为:\(A1 || B1)")
print("!A 结果为:\(!A1)")
print("!B 结果为:\(!B1)")
//24.3位运算符
var A2 = 60 // 二进制为 0011 1100
var B2 = 13 // 二进制为 0000 1101
print("A&B 结果为:\(A2&B2)")
print("A|B 结果为:\(A2|B2)")
print("A^B 结果为:\(A2^B2)")
print("~A 结果为:\(~A2)")
//24.4赋值运算符
var A4 = 10
var B4 = 20
var C4 = 100
C4 = A4 + B4
print("C 结果为:\(C4)")
C4 += A4
print("C 结果为:\(C4)")
C4 -= A4
print("C 结果为:\(C4)")
C4 *= A4
print("C 结果为:\(C4)")
C4 /= A4
print("C 结果为:\(C4)")
//区间运算符
print("闭区间运算符:")
for index in 1...5 {
print("\(index) * 5 = \(index * 5)")
}
print("半开区间运算符:")
for index in 1..<5 {
print("\(index) * 5 = \(index * 5)")
}
//其他运算符
var A5 = 1
var B5 = 2
var C5 = true
var D5 = false
print("-A 的值为:\(-A5)")
print("A + B 的值为:\(A5 + B5)")
print("三元运算:\(C5 ? A5 : B5 )")
print("三元运算:\(D5 ? A5 : B5 )")
//---------------------------------------------------------------------------------------------------
//25.条件语句
/**
Swift 提供了以下几种类型的条件语句:
语句 描述
if 语句
if 语句 由一个布尔表达式和一个或多个执行语句组成。
if...else 语句
if 语句 后可以有可选的 else 语句, else 语句在布尔表达式为 false 时执行。
if...else if...else 语句
if 后可以有可选的 else if...else 语句, else if...else 语句常用于多个条件判断。
内嵌 if 语句
你可以在 if 或 else if 中内嵌 if 或 else if 语句。
switch 语句
switch 语句允许测试一个变量等于多个值时的情况。
*/
if A1 {
print("true")
}
if A1 {
print("true")
}else{
print("false")
}
if A2 > A4 {
print("1")
}else if A2 == A4{
print("2")
}else{
print("3")
}
if A1 {
if A2 > A4 {
print("true")
}
}
var index = 10
switch index {
case 100 :
print( "index 的值为 100")
case 10,15 :
print( "index 的值为 10 或 15")
case 5 :
print( "index 的值为 5")
default :
print( "默认 case")
}
switch index {
case 100 :
print( "index 的值为 100")
fallthrough
case 10,15 :
print( "index 的值为 10 或 15")
fallthrough
case 5 :
print( "index 的值为 5")
default :
print( "默认 case")
}
//---------------------------------------------------------------------------------------------------
//26.循环语句
/*
Swift 语言提供了以下几种循环类型。点击链接查看每个类型的详细描述:
循环类型 描述
for-in
遍历一个集合里面的所有元素,例如由数字表示的区间、数组中的元素、字符串中的字符。
for 循环
该循环方式在 Swift 3 中已经弃用。
用来重复执行一系列语句直到达成特定条件达成,一般通过在每次循环完成后增加计数器的值来实现。
while 循环
运行一系列语句,如果条件为true,会重复运行,直到条件变为false。
repeat...while 循环
类似 while 语句区别在于判断循环条件之前,先执行一次循环的代码块。
循环控制语句
循环控制语句改变你代码的执行顺序,通过它你可以实现代码的跳转。Swift 以下几种循环控制语句:
控制语句 描述
continue 语句
告诉一个循环体立刻停止本次循环迭代,重新开始下次循环迭代。
break 语句
中断当前循环。
fallthrough 语句
如果在一个case执行完后,继续执行下面的case,需要使用fallthrough(贯穿)关键字。
*/
//格式: for index in var{}
for inde in 1...5 {
print("index * 5 等于\(inde * 5)")
}
for item in 1..<5 {
print(item)
}
var itemindex:[Int] = [10,20,30]
for i in itemindex {
print(i)
}
/*
for var i = 0;i < 3;++I {
print(itemindex[I])
}
***在swift3中被弃用
*/
// while condition {}
var j = 10;
while j < 20 {
j = j + 1;
print(j)
}
//Swift repeat...while 循环不像 for 和 while 循环在循环体开始执行前先判断条件语句,而是在循环执行结束时判断条件是否符合。
//格式: repeat{} while condition
var k = 15
repeat{
print("k的值为\(k)")
k = k + 1
} while k < 20
// continue ;结束本ci循环,执行下一次循环
// break:终端循环
//fallthrough :继续执行case后面的语句,穿过
//---------------------------------------------------------------------------------------------------
//27.字符串
//创建字符串
var str10 = "mmmmmmmmmm"
print(str10)
var str11 = String("nnnnnnnn")
print(str11)
//空字符串
var stringa = ""
if stringa.isEmpty {
print("字符串是空的")
}else{
print("字符串不是空的")
}
var stringb = String()
if stringb.isEmpty {
print("字符串是空的")
}else{
print("字符串不是空的")
}
//字符串常量
var stringc = "菜鸟教程:"
stringc += "http://www.baidu.com"
print(stringc)
//let stringd = String("菜鸟教程:")
//stringd += "http://www.baidu.com"
//print(stringd)
//字符串中插入值
var varaa = 20;
let constaa = 100
var varcc:Float = 20.0
var stringdd = "\(varaa) 乘以 \(constaa) 等于\(varcc * 100)"
print(stringdd)
//字符串连接
let constaaa = "菜鸟教程:"
let constbb = "http://www.baidu.com"
var stringcc = constaaa + constbb
print(stringcc)
//字符串长度:字符串长度使用 String.count 属性来计算
//Swift 3 版本使用的是 String.characters.count
var varaaaa = "www.runboob.com"
print("字符串的长度为\(varaaaa.count)")
//字符串比较
var varbbbb = "hello,swift"
var varcccc = "hello,world"
if varbbbb == varcccc {
print("\(varbbbb)与\(varcccc)是相等的")
}else{
print("\(varbbbb)与\(varcccc)是不相等的")
}
//Unicode 字符串
var unicodestring = "菜鸟教程"
print("UTF-8:\(unicodestring.utf8)")
for code in unicodestring.utf8 {
print(code)
}
//字符串函数及运算符
if unicodestring.hasPrefix("菜") {
print("有前缀")
}else{
print("无前缀")
}
if unicodestring.hasSuffix("程") {
print("有后缀")
}else{
print("无后缀")
}
var vardddd = "1234"
let intvar = Int(vardddd)
print(intvar!)
//---------------------------------------------------------------------------------------------------
//28.Swift 字符(Character)
let char1:Character = "A"
let char2:Character = "B"
print("char1 的值为\(char1)")
print("char2 的值为\(char2)")
//遍历字符串中的字符
//swift3 中
//for ch in "Runoob".characters {
// print(ch)
//}
//swift4中
for ch in "runboom" {
print(ch)
}
//字符串连接字符
var ee:String = "bbbbbb"
let ff:Character = "B"
print(ee.append( ff))
//---------------------------------------------------------------------------------------------------
//29. Swift 数组
//创建数组:
var arr1 = [Int]()
var arr2:[Int] = [10,20,30]
var arr3 = [Int](repeating: 5, count: 7)
print("\(arr1),\(arr2),\(arr3)")
//访问数组
var ele = arr3[4]
print(ele)
print(arr3[0])
//修改数组
arr3.append(6)
arr3.append(7)
arr3.append(8)
arr3 += [9]
print(arr3)
arr3[0] = 100
print(arr3)
//遍历数组
for item in arr3 {
print(item)
}
//如果我们同时需要每个数据项的值和索引值,可以使用 String 的 enumerate() 方法来进行数组遍历。实例如下:
for (index0,item0) in arr3.enumerated() {
print("索引index \(index0)下的值为\(item0)")
}
//合并数组
var iii = [Int](repeating: 2, count: 6)
var kkkk = [Int](repeating: 9, count: 3)
var lll = iii + kkkk
for (i0,t0) in lll.enumerated() {
print("索引\(i0) 下的值为 \(t0)")
}
//---------------------------------------------------------------------------------------------------
//30.Swift 字典
//创建字典 var dic = [String:int]()
var dic0 = [String:Int]();
var dic1:[Int:String] = [1:"one",2:"two",3:"three"];
print(dic1)
//访问字典
var element = dic1[1]
print(element!)
for (key,value) in dic1 {
print("key is \(key), value is \(value)")
}
//修改字典
dic1[1] = "ooo"
print(dic1)
dic1.updateValue("llll", forKey: 2)
print(dic1)
//删除字典
dic1.removeValue(forKey: 2)
print(dic1)
dic1[1] = nil;
print(dic1)
//遍历字典
for (key,value) in dic1 {
print(key)
print(value)
}
for (key,value) in dic1.enumerated() {
print(key)
print(value)
}
//字典转换为数组
var dic2:[Int:String] = [1:"11111",2:"222222",3:"333333333",4:"444444444444"]
var keyarr = [Int](dic2.keys)
var valueArr = [String](dic2.values);
for keyvar in keyarr {
print(keyarr)
}
for valuevar in valueArr {
print(valuevar)
}
//---------------------------------------------------------------------------------------------------
//31.函数
/**
Swift 函数用来完成特定任务的独立的代码块。
Swift使用一个统一的语法来表示简单的C语言风格的函数到复杂的Objective-C语言风格的方法。
函数声明: 告诉编译器函数的名字,返回类型及参数。
函数定义: 提供了函数的实体。
Swift 函数包含了参数类型及返回值类型:
*/
//格式 func 函数名(形式参数)->返回值类型{
// stament
// stament
// stament
// stament
// stament
// return parameters
//}
//函数调用
func runoob(site:String) ->String{
return site;
}
var haha = runoob(site: "www")
print(haha)
print(runoob(site: "hello,world!"))
//函数参数
func runoob1(site:String,name:String)->String{
return site + name
}
print(runoob1(site: "1111", name: "222222"))
//无参数函数
func runoob2()->String{
return "hhahahahahha"
}
print(runoob2())
//元组作为函数返回值
/**
函数返回值类型可以是字符串,整型,浮点型等。
元组与数组类似,不同的是,元组中的元素可以是任意类型,使用的是圆括号。
你可以用元组(tuple)类型让多个值作为一个复合值从函数中返回。
下面的这个例子中,定义了一个名为minMax(_:)的函数,作用是在一个Int数组中找出最小值与最大值。
*/
func minmax(array:[Int]) ->(min:Int,max:Int)?{
if array.isEmpty{
return nil;
}
var currentmin = array[0]
var currentmax = array[0]
for value in array[1..<array.count] {
if value < currentmin {
currentmin = value
}else if value > currentmax{
currentmax = value
}
}
return (currentmin,currentmax)
}
print(minmax(array: []))
//没有返回值函数
func runoob0(site: String) {
print("菜鸟教程官网:\(site)")
}
runoob0(site: "http://www.runoob.com")
//func runoob3(site:String){
// print("www.hhhhhh")
//}
//
//print(runoob3(site: "dddddd"))
//函数参数名称 :函数参数都有一个外部参数名和一个局部参数名。
func sample(number:Int){
print(number)
}
sample(number: 1)
sample(number: 2)
sample(number: 3)
//外部参数名:你可以在局部参数名前指定外部参数名,中间以空格分隔,外部参数名用于在函数调用时传递给函数的参数。如下你可以定义以下两个函数参数名并调用它:
func pow(firstArg a:Int,secondArg b:Int) ->Int{
var aes = a
for _ in 1..<b {
aes = aes * a
}
print(aes)
return aes;
}
pow(firstArg: 5, secondArg: 3)
//可变参数
/**
可变参数可以接受零个或多个值。函数调用时,你可以用可变参数来指定函数参数,其数量是不确定的。
可变参数通过在变量类型名后面加入(...)的方式来定义。
*/
func vari<N>(numbers:N...){
for ii in numbers {
print(ii)
}
}
vari(numbers: 1,2,3)
vari(numbers: 1,0)
vari(numbers: 1.2,3.4,5.6)
vari(numbers: "ffff","hhhhh","bbbbbb")
//常量,变量及 I/O 参数
/**
一般默认在函数中定义的参数都是常量参数,也就是这个参数你只可以查询使用,不能改变它的值。
如果想要声明一个变量参数,可以在参数定义前加 inout 关键字,这样就可以改变这个参数的值了。
例如:
*/
// func getName(_ name: inout String).........
func swapTwoInt(_ a:inout Int, _ b: inout Int){
let temp = a
a = b
b = temp
}
var x = 10
var y = 20
swap(&x, &y)
print("\(x),\(y)")
//函数类型及使用:每个函数都有种特定的函数类型,由函数的参数类型和返回类型组成。
//var addition:(Int,Int) ->Int = sum
func sum(a:Int,b:Int) ->Int{
return a + b
}
var addition:(Int,Int) ->Int = sum
print(addition(10,100))
//函数类型作为参数类型、函数类型作为返回类型
func another(addition:(Int,Int) ->Int,a:Int,b:Int){
print(addition(a,b))
}
another(addition: sum, a: 10, b: 20)
//函数嵌套
func calcDecrement(forDecrement total: Int) -> () -> Int {
var overallDecrement = 0
func decrementer() -> Int {
overallDecrement -= total
return overallDecrement
}
return decrementer
}
let decrem = calcDecrement(forDecrement: 30)
print(decrem())
//---------------------------------------------------------------------------------------------------
//32.swift闭包
/**
{(parameter) -> return type in
statement
}
*/
let stuname = { print("学生名字叫张三")}
stuname()
//闭包两个参数类型
/**
{(Int,Int) ->Bool in
statement
...
statement
}
*/
let divide = {(value1:Int,value2:Int) ->Int in
return value1 / value2
}
let result = divide(200,20)
print(result)
//闭包表达式:闭包表达式是一种利用简洁语法构建内联闭包的方式。 闭包表达式提供了一些语法优化,使得撰写闭包变得简单明了。
let names = ["AT","AE","D","S","BE"]
func backwards(s1:String,s2:String) ->Bool{
return s1 > s2
}
var resered = names.sorted(by: backwards)
print(resered)
//参数名称缩写:Swift 自动为内联函数提供了参数名称缩写功能,您可以直接通过$0,$1,$2来顺序调用闭包的参数。
var reserve1 = names.sorted(by: >)
print(reserve1)
//尾随闭包:尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。
func someFunctionThatTakesAClosure(closure: () -> Void) {
// 函数体部分
}
someFunctionThatTakesAClosure {
}
someFunctionThatTakesAClosure {
}
//捕获值
/**
闭包可以在其定义的上下文中捕获常量或变量。
即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。
Swift最简单的闭包形式是嵌套函数,也就是定义在其他函数的函数体内的函数。
嵌套函数可以捕获其外部函数所有的参数以及定义的常量和变量。
看这个例子:
*/
func makeIncreter(forIncrement count:Int) ->()->Int{
var runningtotal = 0;
func incrementor()->Int{
runningtotal += count;
return runningtotal
}
return incrementor;
}
let incrementby10 = makeIncreter(forIncrement: 10)
print(incrementby10())
print(incrementby10())
print(incrementby10())
//闭包是引用类型
/**
上面的例子中,incrementByTen是常量,但是这些常量指向的闭包仍然可以增加其捕获的变量值。
这是因为函数和闭包都是引用类型。
无论您将函数/闭包赋值给一个常量还是变量,您实际上都是将常量/变量的值设置为对应函数/闭包的引用。 上面的例子中,incrementByTen指向闭包的引用是一个常量,而并非闭包内容本身。
这也意味着如果您将闭包赋值给了两个不同的常量/变量,两个值都会指向同一个闭包:
*/
let anoter = incrementby10;
print(anoter())
//---------------------------------------------------------------------------------------------------
//32.swift枚举
//格式: enum enumname{}
enum DaysForWeek{
case Sunday
case Monday
case Tuesday
case Wensday
case Tursday
case Friday
case Saturday
}
var weekday = DaysForWeek.Tuesday
switch weekday {
case .Sunday:
print("星期天")
case .Monday:
print("星期一")
case .Tuesday:
print("星期二")
case .Wensday:
print("星期三")
case .Tursday:
print("星期四")
case .Friday:
print("星期五")
case .Saturday:
print("星期六")
}
//相关值
enum Student{
case Name(String)
case Mark(Int,Int,Int)
}
var studentdetails = Student.Name("run")
var studentmarks = Student.Mark(100, 70, 50)
switch studentmarks {
case .Name(let stuname):
print(stuname)
case .Mark(let mark1, let mark2, let mark3):
print("\(mark1),\(mark2),\(mark3)")
}
//原始值
enum Month:Int{
case January = 1, February, March, April, May, June, July, August, September, October, November, December
}
let yearmonth = Month.May.rawValue
print(yearmonth)
//---------------------------------------------------------------------------------------------------
//32.swift结构体
//
/**
struct namestruct{
defi 1
....
defi n
}
*/
struct markStruct{
var mark1:Int = 100
var mark2:Int = 87
var mark3:Int = 50
}
let marks = markStruct()
print(marks.mark3)
struct markstudent{
var mark:Int
init(mark:Int) {
self.mark = mark
}
}
var m = markstudent(mark: 100)
var n = m
n.mark = 120
print(m.mark)
print(n.mark)
//结构体应用
struct marksaa{
var mark1:Int
var mark2:Int
var mark3:Int
init(mark1:Int,mark2:Int,mark3:Int) {
self.mark1 = mark1
self.mark2 = mark2
self.mark3 = mark3
}
}
var mm = marksaa(mark1: 100, mark2: 101, mark3: 102)
print(mm.mark1)
print(mm.mark2)
print(mm.mark3)
//---------------------------------------------------------------------------------------------------
//32.swift类
class clasname{
var studentname:String = ""
var mark:Int = 30
var mark2:Int = 30
}
let cls = clasname()
class clsStruct{
var mark:Int
init(mark:Int) {
self.mark = mark
}
}
let clss = clsStruct(mark: 100)
print(clss.mark)
class studentmark{
var mark = 300
}
let stu = studentmark()
print(stu.mark)
//作为引用类型访问类属性
/**
因为类是引用类型,有可能有多个常量和变量在后台同时引用某一个类实例。
为了能够判定两个常量或者变量是否引用同一个类实例,Swift 内建了两个恒等运算符:
*/
class sampleClass:Equatable{
let myproperty:String
init(s:String) {
self.myproperty = s
}
}
func == (lhs:sampleClass,rhs:sampleClass) ->Bool{
return lhs.myproperty == rhs.myproperty
}
let spclass = sampleClass(s: "hello")
let spclass2 = sampleClass(s: "hello")
if spclass === spclass2 {
print("引用是同一个实力")
}
if spclass !== spclass2 {
print("引用非同一个实力")
}
//---------------------------------------------------------------------------------------------------
//33.swift属性
struct Number{
var digital:Int
let pi = 3.1415926
}
var t = Number(digital: 12345)
t.digital = 67
print(t.pi)
//延迟存储属性
class number{
var name = "hello bunbool"
}
class sample1{
lazy var no = number()
}
var sampl = sample1()
print(sampl.no.name)
//计算属性: 除存储属性外,类、结构体和枚举可以定义计算属性,计算属性不直接存储值,而是提供一个 getter 来获取值,一个可选的 setter 来间接设置其他属性或变量的值。
class sample2{
var no1 = 0.0,no2 = 0.0
var length = 300.0,breathe = 150.0;
var middle:(Double,Double){
set(axis){
no1 = axis.0 - length/2
no2 = axis.1 - breathe/2
}
get{
return (length/2,breathe/2)
}
}
}
var resul = sample2()
print(resul.middle)
resul.middle = (1000.0,2000.0)
print(resul.no1)
print(resul.no2)
//只读计算属性
class film{
var head = ""
var duration = 0.0
var metainfo:[String:String]{
return ["head":self.head,"duration":"\(self.duration)"]
}
}
var fil = film()
fil.head = "swift shuxing"
fil.duration = 3.09
print(fil.metainfo["head"]!)
print(fil.metainfo["duration"]!)
//属性观察器:
/**
属性观察器监控和响应属性值的变化,每次属性被设置值的时候都会调用属性观察器,甚至新的值和现在的值相同的时候也不例外。
可以为除了延迟存储属性之外的其他存储属性添加属性观察器,也可以通过重载属性的方式为继承的属性(包括存储属性和计算属性)添加属性观察器。
注意:
不需要为无法重载的计算属性添加属性观察器,因为可以通过 setter 直接监控和响应值的变化。
可以为属性添加如下的一个或全部观察器:
willSet在设置新的值之前调用
didSet在新的值被设置之后立即调用
willSet和didSet观察器在属性初始化过程中不会被调用
*/
class samplergm{
var counter:Int = 0{
willSet(newTotal){
print("计数器:\(newTotal)")
}
didSet{
if counter > oldValue {
print("新增数: \(counter - oldValue)")
}
}
}
}
let newcounter = samplergm()
newcounter.counter = 100
newcounter.counter = 800
//全局变量和局部变量
//类型属性
struct structname{
static var storeTypeproperty = 12
static var computerTypeProperty:Int{
return storeTypeproperty/2
}
}
enum enumName{
static var storeTypeProperrty = 30
static var compterTypeproperty:Int{
return storeTypeProperrty/2
}
}
class classsName{
class var computerTypeProperty:Int{
return 100
}
}
//获取和设置类型属性的值
struct StuMarks{
static let markcount = 97
static var totalcount = 0
var interMarks:Int = 0{
didSet{
if interMarks > StuMarks.markcount {
interMarks = StuMarks.markcount
}
if interMarks > StuMarks.totalcount {
StuMarks.totalcount = interMarks;
}
}
}
}
var stumark1 = StuMarks()
var stumark2 = StuMarks()
stumark1.interMarks = 98
print(stumark1.interMarks)
stumark2.interMarks = 87
print(stumark2.interMarks)
//---------------------------------------------------------------------------------------------------
//34.swift方法
class Counter{
var count = 0
func increment(){
count += 1
}
func incrementBy(amount:Int){
count += amount
}
func reset(){
count = 0
}
}
let counter = Counter()
counter.increment()
counter.incrementBy(amount: 100)
counter.reset()
//方法的局部参数名称和外部参数名称
//方法的局部参数名称
class division{
var counter:Int = 0
func incrementBy(no1:Int,no2:Int){
counter = no1 / no2
print(counter)
}
}
let div = division()
div.incrementBy(no1: 300, no2: 3)
//方法外部参数名称
class division1{
var counter:Int = 0
func incrementBy(firstParater no1:Int,secondparater no2:Int){
counter = no1 / no2
print(counter)
}
}
let div1 = division1()
div1.incrementBy(firstParater: 300, secondparater: 100)
//self 属性
class caculates{
let a:Int
let b:Int
let res:Int
init(a:Int,b:Int) {
self.a = a
self.b = b
res = a + b
print("result:\(res)")
}
func tot(c:Int) -> Int {
return res - c
}
func result() {
print("计算结果为\(res)")
}
}
let cal = caculates(a: 100, b: 200)
print(cal.tot(c: 5))
print(cal.result())
//在实例方法中修改值类型
/**
Swift 语言中结构体和枚举是值类型。一般情况下,值类型的属性不能在它的实例方法中被修改。
但是,如果你确实需要在某个具体的方法中修改结构体或者枚举的属性,你可以选择变异(mutating)这个方法,然后方法就可以从方法内部改变它的属性;并且它做的任何改变在方法结束时还会保留在原始结构中。
方法还可以给它隐含的self属性赋值一个全新的实例,这个新实例在方法结束后将替换原来的实例。
*/
struct area{
var length = 1
var breath = 1
func area() -> Int {
return length * breath
}
mutating func saleBy(res:Int) {
length *= res
breath *= res
print(length)
print(breath)
}
}
var val = area(length: 100, breath: 5)
val.saleBy(res: 3)
print(val.length)
print(val.breath)
//在可变方法中给 self 赋值
struct area1{
var length = 1
var breath = 1
func area() -> Int {
return length * breath
}
mutating func saleBy(res:Int) {
self.length *= res
self.breath *= res
print(length)
print(breath)
}
}
var val1 = area1(length: 100, breath: 5)
val1.saleBy(res: 3)
print(val.length)
print(val.breath)
//类型方法
/**
实例方法是被类型的某个实例调用的方法,你也可以定义类型本身调用的方法,这种方法就叫做类型方法。
声明结构体和枚举的类型方法,在方法的func关键字之前加上关键字static。类可能会用关键字class来允许子类重写父类的实现方法。
类型方法和实例方法一样用点号(.)语法调用。
*/
struct abs{
static func absc(number:Int) ->Int{
if number < 0 {
return -number;
}else{
return number
}
}
}
var abss = abs.absc(number: -100)
class abssk{
class func absc(number:Int) ->Int{
if number < 0 {
return -number
}else{
return number
}
}
}
var v = abssk.absc(number: -3)
//---------------------------------------------------------------------------------------------------
//35.Swift 下标脚本
/**
下标脚本 可以定义在类(Class)、结构体(structure)和枚举(enumeration)这些目标中,可以认为是访问对象、集合或序列的快捷方式,不需要再调用实例的特定的赋值和访问方法。
举例来说,用下标脚本访问一个数组(Array)实例中的元素可以这样写 someArray[index] ,访问字典(Dictionary)实例中的元素可以这样写 someDictionary[key]。
对于同一个目标可以定义多个下标脚本,通过索引值类型的不同来进行重载,而且索引值的个数可以是多个。
*/
/**
subscript(index:Int) ->Int{
set(newvalue){
}
get{
}
}
*/
struct subexample{
let december:Int
subscript(index:Int) ->Int{
return december / index
}
}
let su = subexample(december: 300)
print(su[1])
print(su[2])
print(su[3])
print(su[4])
print(su[5])
print(su[6])
class daysOfweek{
private var days:[String] = ["1","2","3","4","5","6"]
subscript(index:Int) ->String{
set(newvalue){
self.days[index] = newvalue
}
get{
return self.days[index]
}
}
}
var p = daysOfweek()
print(p[0])
print(p[1])
print(p[2])
print(p[3])
//下标脚本选项
struct Matrix {
let rows: Int, columns: Int
var print: [Double]
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
print = Array(repeating: 0.0, count: rows * columns)
}
subscript(row: Int, column: Int) -> Double {
get {
return print[(row * columns) + column]
}
set {
print[(row * columns) + column] = newValue
}
}
}
// 创建了一个新的 3 行 3 列的Matrix实例
var mat = Matrix(rows: 3, columns: 3)
// 通过下标脚本设置值
mat[0,0] = 1.0
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0
//---------------------------------------------------------------------------------------------------
//35.Swift 继承
/**
继承我们可以理解为一个类获取了另外一个类的方法和属性。
当一个类继承其它类时,继承类叫子类,被继承类叫超类(或父类)
在 Swift 中,类可以调用和访问超类的方法,属性和下标脚本,并且可以重写它们。
我们也可以为类中继承来的属性添加属性观察器。
*/
class studentDetail{
var stname:String!
var mark:Int!
var mark1:Int!
var mark2:Int!
init(stname:String,mark:Int,mark1:Int,mark2:Int) {
self.stname = stname
self.mark = mark
self.mark1 = mark1
self.mark2 = mark2
}
}
let stname = "swift"
let mark = 100
let mark1 = 100
let mark2 = 100
var student = studentDetail(stname: stname, mark: mark, mark1: mark1, mark2: mark2)
print(student.stname!)
print(student.mark!)
print(student.mark1!)
print(student.mark2!)
//子类
//class stu:studentDetail{
//
//}
class studentdet{
var mark:Int;
var mark1:Int;
init(st:Int,results stm2:Int) {
mark = st
mark1 = stm2
}
func show() {
print("\(self.mark),\(self.mark1)")
}
}
class tom:studentdet{
init() {
super.init(st: 100, results: 200)
}
}
//重写(Overriding):子类可以通过继承来的实例方法,类方法,实例属性,或下标脚本来实现自己的定制功能,我们把这种行为叫重写(overriding)。
//我们可以使用 override 关键字来实现重写。
//重写方法和属性
//重写方法
//在我们的子类中我们可以使用 override 关键字来重写超类的方法。
class superclass{
func show() {
print("super")
}
}
class subclass:superclass{
override func show() {
print("sub")
}
}
//重写属性
/**
你可以提供定制的 getter(或 setter)来重写任意继承来的属性,无论继承来的属性是存储型的还是计算型的属性。
子类并不知道继承来的属性是存储型的还是计算型的,它只知道继承来的属性会有一个名字和类型。所以你在重写一个属性时,必需将它的名字和类型都写出来。
注意点:
如果你在重写属性中提供了 setter,那么你也一定要提供 getter。
如果你不想在重写版本中的 getter 里修改继承来的属性值,你可以直接通过super.someProperty来返回继承来的值,其中someProperty是你要重写的属性的名字。
以下实例我们定义了超类 Circle 及子类 Rectangle, 在 Rectangle 类中我们重写属性 area:
*/
class circle{
var radius:Int = 12
var area:String{
return "圆的半径为\(radius)"
}
}
class rantage:circle{
var print = 7
override var area: String{
return super.area + ",但现在被重写为\(print)"
}
}
//重写属性观察器
class cir{
var radius = 12.5
var area:String{
return "举行的半径为\(radius)"
}
}
class retangle:cir{
var print = 7
override var area: String{
return super.area + ",但被重写为\(print)"
}
}
class suqure:retangle{
override var radius: Double{
didSet{
print = Int(radius/5.0) + 1
}
}
}
//---------------------------------------------------------------------------------------------------
//35.Swift 构造过程
/**
构造过程是为了使用某个类、结构体或枚举类型的实例而进行的准备过程。这个过程包含了为实例中的每个属性设置初始值和为其执行必要的准备和初始化任务。
Swift 构造函数使用 init() 方法。
与 Objective-C 中的构造器不同,Swift 的构造器无需返回值,它们的主要任务是保证新实例在第一次使用前完成正确的初始化。
类实例也可以通过定义析构器(deinitializer)在类实例释放之前执行清理内存的工作。
*/
struct rect{
var length:Double
var breathe:Double
var area:Double
init(formlength length:Double, frombreathe breathe:Double) {
self.length = length
self.breathe = breathe
area = length * breathe
}
}
let ar = rect(formlength: 100, frombreathe: 200)
print(ar.area)
//内部和外部参数名
//如果你在定义构造器时没有提供参数的外部名字,Swift 会为每个构造器的参数自动生成一个跟内部名字相同的外部名。
struct color1{
let red,green,blue:Double
init(red:Double,green:Double,blue:Double) {
self.red = red
self.green = green
self.blue = blue
}
init(white:Double) {
red = white
green = white
blue = white
}
}
let color = color1(red: 1.0, green: 0.0, blue: 1.0)
//没有外部名称参数
struct rect2{
var length:Double
init(frombreathe breathe:Double) {
length = breathe * 10
}
init(fromlength leng:Double) {
length = leng * 10
}
init(_ area:Double) {
length = area
}
}
let area00 = rect2(fromlength: 100)
let area2 = rect2(frombreathe: 200)
let area3 = rect2(300)
//可选属性类型
//值类型的构造器代理
struct Size {
var width = 0.0,height = 0.0
}
struct Point{
var x = 0.0,y = 0.0
}
struct Rect{
var origin = Point()
var size = Size()
init() {
}
init(origin:Point, size:Size) {
self.origin = origin
self.size = size
}
init(center:Point,size:Size) {
let originX = center.x - size.width/2
let originY = center.y - size.height/2
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
let basicRect = Rect()
let originRect = Rect(origin: Point(x: 5, y: 10), size: Size(width: 100, height: 200))
let centerRect = Rect(center: Point(x: 50, y: 50), size: Size(width: 120, height: 120))
//指定构造器实例
class mainClass{
var no1:Int
init(no1:Int) {
self.no1 = no1
}
}
class Subclass:mainClass{
var no2:Int
init(no2:Int,no1:Int) {
self.no2 = no2
super.init(no1: no1)
}
//便立构造器
override convenience init(no1:Int) {
self.init(no2:100, no1:no1)
}
}
let maincla = mainClass(no1: 100)
let sub = Subclass(no2: 100, no1: 200)
//便利构造器实例
//构造器的继承和重载
class SUperclass{
var corners = 4
var des:String{
return "\(corners)条边"
}
}
let superc = SUperclass()
print(superc.des)
class SUbclass:SUperclass{
override init() {
super.init()
self.corners = 5
}
}
let subc = SUbclass()
print(subc.des)
//指定构造器和便利构造器实例
class MainClass{
var name:String
init(name:String) {
self.name = name
}
convenience init() {
self.init(name:"匿名")
}
}
class SUBclass:MainClass{
var count:Int
init(name:String,count:Int) {
self.count = count
super.init(name: name)
}
override convenience init(name:String) {
self.init(name:name,count:1)
}
}
let m1 = MainClass(name: "haha")
print(m1.name)
let m2 = MainClass()
print(m2.name)
let s1 = SUBclass(name: "11111", count: 123)
print(s1.name)
let s2 = SUBclass(name: "ttttt")
print(s2.name)
//类的可失败构造器
/**
如果一个类,结构体或枚举类型的对象,在构造自身的过程中有可能失败,则为其定义一个可失败构造器。
变量初始化失败可能的原因有:
传入无效的参数值。
缺少某种所需的外部资源。
没有满足特定条件。
为了妥善处理这种构造过程中可能会失败的情况。
你可以在一个类,结构体或是枚举类型的定义中,添加一个或多个可失败构造器。其语法为在init关键字后面加添问号(init?)。
*/
struct Animal{
let species:String
init?(species:String){
if species.isEmpty {
return nil
}
self.species = species
}
}
let species = Animal(species: "大象")
if let ss = species {
print(ss.species)
}
//枚举类型的可失败构造器
enum Temperrature{
case Kelvin,Celsius,Fahrenheit
init?(smybal:String) {
switch smybal {
case "k":
self = .Kelvin
case "C":
self = .Celsius
case "F":
self = .Fahrenheit
default:
return nil
}
}
}
let temp = Temperrature(smybal: "F")
if temp != nil {
print("初始化成功")
}
let temp1 = Temperrature(smybal: "m")
if temp1 == nil {
print("初始化不成功")
}
//类的可失败构造器
class stuRecord{
let stuname:String!
init?(stuname:String) {
self.stuname = stuname
if stuname.isEmpty {
return nil
}
}
}
//覆盖一个可失败构造器
class Planet {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[No Planets]")
}
}
let plName = Planet(name: "Mercury")
print("行星的名字是: \(plName.name)")
let noplName = Planet()
print("没有这个名字的行星: \(noplName.name)")
class planets: Planet {
var count: Int
init(name: String, count: Int) {
self.count = count
super.init(name: name)
}
override convenience init(name: String) {
self.init(name: name, count: 1)
}
}
//---------------------------------------------------------------------------------------------------
//35.Swift 析构过程
/**
在一个类的实例被释放之前,析构函数被立即调用。用关键字deinit来标示析构函数,类似于初始化函数用init来标示。析构函数只适用于类类型。
*/
var counter0 = 0;
class BasicClass{
init() {
counter0 += 1
}
deinit {
counter0 -= 1
}
}
print(counter0)
var show:BasicClass? = BasicClass()
print(counter0)
show = nil
print(counter0)
//---------------------------------------------------------------------------------------------------
//35.Swift 可选链
class Person{
var residence:Residence?
}
class Residence{
var numberOfroom = 1
}
let pers = Person()
let roomcount = pers.residence?.numberOfroom
print(roomcount)
//为可选链定义模型类
class Address{
var buildingName:String?
var buildingNumber:String?
var street:String?
func buildidentity() -> String? {
if buildingName != nil {
return buildingName
}else if buildingNumber != nil{
return buildingNumber
}else{
return nil
}
}
}
class ROOM{
let name:String
init(name:String) {
self.name = name
}
}
class REDs{
var rooms = [ROOM]()
var numberofroom:Int{
return rooms.count
}
subscript(index:Int) ->ROOM{
return rooms[index]
}
func printnumberofrooms() {
print(numberofroom)
}
var address:Address?
}
class perso{
var res:REDs?
}
//通过可选链调用方法
let json = perso()
if json.res?.printnumberofrooms() != nil {
print("输出房间号")
}else{
print("无法输出房间号")
}
//使用可选链调用下标脚本
let tom9 = perso()
if let name = tom9.res?[0].name {
print("第一个房间名 \(name).")
}else{
print("无法检索到房间")
}
//
let hks = perso()
let hksofhourse = REDs()
hksofhourse.rooms.append(ROOM(name: "厨房"))
hksofhourse.rooms.append(ROOM(name: "客厅"))
hks.res = hksofhourse;
let address = Address()
address.buildingName = "kkkkk"
address.street = "hhhhhhhhh"
hks.res?.address = address
if let street = hks.res?.address?.street {
print("John 所在的街道是 \(street)。")
}else{
print("无法检索到地址。 ")
}
//通过可选链接调用来访问下标
if let firstRoomName = hks.res?[0].name {
print("第一个房间名为\(firstRoomName)")
}else{
print("无法检索到房间")
}
//访问可选类型的下标
//---------------------------------------------------------------------------------------------------
//35.Swift 自动引用计数(ARC)
class Person1{
var name:String
init(name:String) {
self.name = name
print("\(name)被创建")
}
deinit {
print("\(name)被析构")
}
}
var prefence0:Person1?
var prefence1:Person1?
var prefence2:Person1?
prefence0 = Person1(name: "run")
prefence1 = prefence0
prefence2 = prefence1
prefence0 = nil
prefence1 = nil
prefence2 = nil
//类实例之间的循环强引用
class person2{
let name:String
init(name:String) {
self.name = name
}
var apartment:Apartment?
deinit {
print("\(name)被洗")
}
}
class Apartment{
let number:Int
init(number:Int) {
self.number = number
}
var talent:person2?
deinit {
print("\(number)被洗")
}
}
var runbool:person2?
var number73:Apartment?
runbool = person2(name: "run2")
number73 = Apartment(number: 73)
runbool?.apartment = number73;
number73?.talent = runbool
runbool = nil
number73 = nil
/**
Swift 提供了两种办法用来解决你在使用类的属性时所遇到的循环强引用问题:
弱引用
无主引用
弱引用和无主引用允许循环引用中的一个实例引用另外一个实例而不保持强引用。这样实例能够互相引用而不产生循环强引用。
对于生命周期中会变为nil的实例使用弱引用。相反的,对于初始化赋值后再也不会被赋值为nil的实例,使用无主引用。
*/
//弱引用实例
class Module{
var name:String
init(name:String) {
self.name = name
}
var sub:subModule?
deinit {
print("\(name)悲喜狗")
}
}
class subModule{
let number:Int
init(number:Int) {
self.number = number
}
weak var mo:Module?
deinit {
print("\(number)悲喜狗")
}
}
var module:Module?
var sub1:subModule?
module = Module(name: "run2")
sub1 = subModule(number: 123)
module?.sub = sub1;
sub1?.mo = module;
module = nil
sub1 = nil;
//无主引用实例
class Student0{
var name:String
init(name:String) {
self.name = name
}
var section:marks0?
deinit {
print("\(name)悲喜狗")
}
}
class marks0{
let mark:Int
unowned let stame:Student0
init(mark:Int,stname:Student0) {
self.mark = mark
self.stame = stname
}
deinit {
print("\(mark)悲喜狗")
}
}
var student0:Student0?
student0 = Student0(name: "arc")
student0?.section = marks0(mark: 98, stname: student0!)
student0 = nil
//闭包引起的循环强引用
/**
循环强引用还会发生在当你将一个闭包赋值给类实例的某个属性,并且这个闭包体中又使用了实例。这个闭包体中可能访问了实例的某个属性,例如self.someProperty,或者闭包中调用了实例的某个方法,例如self.someMethod。这两种情况都导致了闭包 "捕获" self,从而产生了循环强引用。
*/
class HTMLELEMENT{
let name:String
let text:String?
lazy var ashtml:()->String = {
[unowned self] in
if let text = self.text {
return "1"
}else{
return "0"
}
}
init(name:String,text:String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name)悲喜狗")
}
}
var para:HTMLELEMENT? = HTMLELEMENT(name: "p", text: "hello")
print(para?.ashtml())
para = nil
//---------------------------------------------------------------------------------------------------
//35.Swift 类型转换
/**
Swift 语言类型转换可以判断实例的类型。也可以用于检测实例类型是否属于其父类或者子类的实例。
Swift 中类型转换使用 is 和 as 操作符实现,is 用于检测值的类型,as 用于转换类型。
类型转换也可以用来检查一个类是否实现了某个协议。
*/
class Subjects{
var physics:String
init(physics:String) {
self.physics = physics
}
deinit {
}
}
class Chemistry:Subjects{
var equations:String
init(physics:String,equations:String) {
self.equations = equations
super.init(physics: physics)
}
}
class Maths:Subjects{
var formulae:String
init(physics:String,formulae:String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let sa = [Chemistry(physics: "固体物理", equations: "赫兹"),Maths(physics: "流体动力学", formulae: "千兆赫")]
let samplechem = Chemistry(physics: "固体物理", equations: "赫兹")
print(samplechem.physics)
print(samplechem.equations)
let sampleMaths = Maths(physics: "流体动力学", formulae: "千兆赫")
print(sampleMaths.physics)
print(sampleMaths.formulae)
//检查类型
/**
类型转换用于检测实例类型是否属于特定的实例类型。
你可以将它用在类和子类的层次结构上,检查特定类实例的类型并且转换这个类实例的类型成为这个层次结构中的其他类型。
类型检查使用 is 关键字。
操作符 is 来检查一个实例是否属于特定子类型。若实例属于那个子类型,类型检查操作符返回 true,否则返回 false。
*/
let sa1 = [Chemistry(physics: "固体物理", equations: "赫兹"),
Maths(physics: "流体动力学", formulae: "千兆赫"),
Chemistry(physics: "热物理", equations: "分贝"),
Maths(physics: "天体物理学", formulae: "兆赫"),
Maths(physics: "微分方程", formulae: "三角函数")]
var chemcount = 0;
var mathcount = 0;
for item in sa1 {
if item is Chemistry {
chemcount += 1
} else if item is Maths{
mathcount += 1
}
}
print("化学\(chemcount)个,数学\(mathcount)个")
//向下转型
/**
向下转型,用类型转换操作符(as? 或 as!)
当你不确定向下转型可以成功时,用类型转换的条件形式(as?)。条件形式的类型转换总是返回一个可选值(optional value),并且若下转是不可能的,可选值将是 nil。
只有你可以确定向下转型一定会成功时,才使用强制形式(as!)。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。
*/
for item1 in sa1 {
if let show = item1 as? Chemistry {
print(show.physics)
print(show.equations)
}else if let example = item1 as? Maths{
print(example.physics)
print(example.formulae)
}
}
//Any和AnyObject的类型转换
/**
Swift为不确定类型提供了两种特殊类型别名:
AnyObject可以代表任何class类型的实例。
Any可以表示任何类型,包括方法类型(function types)。
注意:
只有当你明确的需要它的行为和功能时才使用Any和AnyObject。在你的代码里使用你期望的明确的类型总是更好的。
*/
// Any 实例
var exampleAny = [Any]()
exampleAny.append(12)
exampleAny.append(12.345)
exampleAny.append("ddddd")
exampleAny.append(Chemistry(physics: "固体物理", equations: "赫兹"))
for item2 in exampleAny {
switch item2 {
case let someint as Int:
print(someint)
case let somedouble as Double where somedouble > 0:
print(somedouble)
case let somestring as String:
print(somestring)
case let somephy as Chemistry:
print(somephy)
default:
print("none")
}
}
//AnyObject 实例
let sa2:[AnyObject] = [Chemistry(physics: "固体物理", equations: "赫兹"),
Maths(physics: "流体动力学", formulae: "千兆赫"),
Chemistry(physics: "热物理", equations: "分贝"),
Maths(physics: "天体物理学", formulae: "兆赫"),
Maths(physics: "微分方程", formulae: "三角函数")]
//---------------------------------------------------------------------------------------------------
//37.Swift 扩展
/**
扩展就是向一个已有的类、结构体或枚举类型添加新功能。
扩展可以对一个类型添加新的功能,但是不能重写已有的功能。
Swift 中的扩展可以:
添加计算型属性和计算型静态属性
定义实例方法和类型方法
提供新的构造器
定义下标
定义和使用新的嵌套类型
使一个已有类型符合某个协议
*/
//extension someType{
//
//}
//extension SomeType: SomeProtocol, AnotherProctocol {
// // 协议实现写到这里
//}
//计算型属性
//扩展可以向已有类型添加计算型实例属性和计算型类型属性。
//实例
//下面的例子向 Int 类型添加了 5 个计算型实例属性并扩展其功能:
extension Int{
var add:Int{
return self + 100
}
var sub:Int{
return self - 100
}
var mul:Int{
return self * 100
}
var div:Int{
return self / 5
}
}
let addi = 100.add
print(addi)
let su0 = 200.sub
print(su0)
let mul = 100.mul
print(mul)
let div11 = 500.div
print(div11)
let coll = 3.add + 500.mul
print(coll)
//构造器
//扩展可以向已有类型添加新的构造器。
//这可以让你扩展其它类型,将你自己的定制类型作为构造器参数,或者提供该类型的原始实现中没有包含的额外初始化选项。
//扩展可以向类中添加新的便利构造器 init(),但是它们不能向类中添加新的指定构造器或析构函数 deinit() 。
struct summ{
var num1 = 100,num2 = 200;
}
struct diff{
var no1 = 200, no2 = 100;
}
struct mult{
var a = summ()
var b = diff()
}
extension mult{
init(x:summ,y:diff) {
_ = x.num1 + x.num2
_ = y.no1 + y.no2
}
}
let ax = summ(num1: 100, num2: 200)
let by = diff(no1: 200, no2: 100)
let getmul = mult(x: ax, y: by)
print(getmul.a.num1)
//方法
//扩展可以向已有类型添加新的实例方法和类型方法。
//下面的例子向Int类型添加一个名为 topics 的新实例方法:
extension Int{
func topics(summations:()->()) {
for _ in 0...self {
summations()
}
}
}
10.topics {
print("11111111")
}
//可变实例方法
//通过扩展添加的实例方法也可以修改该实例本身。
//结构体和枚举类型中修改self或其属性的方法必须将该实例方法标注为mutating,正如来自原始实现的修改方法一样。
extension Double{
mutating func squre() {
let pi = 3.1415
self = self * self * pi
}
}
var tri = 3.3
tri.squre()
print(tri)
//下标
//扩展可以向一个已有类型添加新下标。
//实例
//以下例子向 Swift 内建类型Int添加了一个整型下标。该下标[n]返回十进制数字
//extension Int {
// subscript( multtable: Int) -> Int {
// var no1 = 1
// while multtable > 0 {
// no1 *= 10
// multtable - 1
// }
// return (self / no1) % 10
// }
//}
//
//print(12[0])
//print(7869[1])
//print(786543[2])
//嵌套类型
//扩展可以向已有的类、结构体和枚举添加新的嵌套类型:
//---------------------------------------------------------------------------------------------------
//37.Swift 协议
/**
协议规定了用来实现某一特定功能所必需的方法和属性。
任意能够满足协议要求的类型被称为遵循(conform)这个协议。
类,结构体或枚举类型都可以遵循协议,并提供具体实现来完成协议定义的方法和功能。
*/
//protocol somrprotocol{
// //
//}
//struct SomeStructure: FirstProtocol, AnotherProtocol {
// // 结构体内容
//}
//class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
// // 类的内容
//}
//对属性的规定
/**
协议用于指定特定的实例属性或类属性,而不用指定是存储型属性或计算型属性。此外还必须指明是只读的还是可读可写的。
协议中的通常用var来声明变量属性,在类型声明后加上{ set get }来表示属性是可读可写的,只读属性则用{ get }来表示。
*/
protocol classa{
var marks:Int{set get}
var result:Bool{get}
func attendence() -> String
func macsuccedd() -> String
}
protocol classb:classa{
var present:Bool {set get}
var subject:String{set get}
var stname:String{set get}
}
class classc:classb{
var marks = 96
let result: Bool = true
var present: Bool = false
var subject: String = "swift协议"
var stname: String = "procotpl"
func attendence() -> String {
return "attendce"
}
func macsuccedd() -> String {
return "macsucceed"
}
}
let dent = classc()
dent.stname = "swift"
dent.marks = 100
dent.macsuccedd()
print(dent.marks)
print(dent.result)
print(dent.present)
print(dent.subject)
print(dent.stname)
//对 Mutating 方法的规定
/**
有时需要在方法中改变它的实例。
例如,值类型(结构体,枚举)的实例方法中,将mutating关键字作为函数的前缀,写在func之前,表示可以在该方法中修改它所属的实例及其实例属性的值。
*/
protocol dayssofaweek{
mutating func show()
}
enum days:dayssofaweek{
case sun,mon,tue,wed,thurs,fri,sat
mutating func show() {
switch self {
case .sun:
self = .sun
print("sun")
case .mon:
self = .mon
print("mon")
case .tue:
self = .tue
print("tue")
case .wed:
self = .wed
print("wed")
case .thurs:
self = .thurs
print("thurs")
case .fri:
self = .fri
print("fri")
case .sat:
self = .sat
print("sun")
default:
print("no such day")
}
}
}
var res = days.wed
res.show()
//对构造器的规定
/**
协议可以要求它的遵循者实现指定的构造器。
你可以像书写普通的构造器那样,在协议的定义里写下构造器的声明,但不需要写花括号和构造器的实体,语法如下:
*/
//protocol SomeProtocol {
// init(someParameter: Int)
//}
protocol tcpprotocol{
init(aport:Int)
}
//协议构造器规定在类中的实现
/**
你可以在遵循该协议的类中实现构造器,并指定其为类的指定构造器或者便利构造器。在这两种情况下,你都必须给构造器实现标上"required"修饰符
*/
class someClass:tcpprotocol{
required init(aport: Int) {
//构造器实现
}
}
/**
使用required修饰符可以保证:所有的遵循该协议的子类,同样能为构造器规定提供一个显式的实现或继承实现。
如果一个子类重写了父类的指定构造器,并且该构造器遵循了某个协议的规定,那么该构造器的实现需要被同时标示required和override修饰符:
*/
protocol tcpprotocol1{
init(no1:Int)
}
class mainClass1{
var no1:Int
init(no1:Int) {
self.no1 = no1
}
}
class subclass1:mainClass1,tcpprotocol1{
var no2:Int
init(no1:Int,no2:Int) {
self.no2 = no2
super.init(no1: no1)
}
required override convenience init(no1: Int) {
self.init(no1:no1,no2:0)
}
}
let res00 = mainClass1(no1: 20)
let show00 = subclass1(no1: 30, no2: 50)
print(res00.no1)
print(show00.no1)
print(show00.no2)
//协议类型
/**
尽管协议本身并不实现任何功能,但是协议可以被当做类型来使用。
协议可以像其他普通类型一样使用,使用场景:
作为函数、方法或构造器中的参数类型或返回值类型
作为常量、变量或属性的类型
作为数组、字典或其他容器中的元素类型
实例
*/
网友评论