swift 最基本的学习结束了,但是很多细节问题都没有搞的太明白,看以后的使用情况吧,在应用中再深入理解。明天就可以用swift开发项目了,高兴!
//: Playground - noun: a place where people can play
import UIKit
/*---------------------1.Swift的基本数据类型-----------------------------*/
var study = 0
if study < 100
{
//1.1 Swift 关键字和标示符
//这样会报错
//var class = 2;
var `class` = 2 //可以这样定义于标示符冲突的变量,但是不建议
/*
关键字分四类:声明相关的(private)语句相关的(break)类型表达式相关的(self)。特定上下文相关的(left,lazy)。
*/
//变量的声明必须确定类型,可以自己显示的指定,也可以初始化让系统推断类型,下面都可以。
var b:Int
var a = 10
var c :Int = 100
//也可以一次声明多个变量,类型也不需要相同
var d=20,e:Int,f="hello "
//常量声明用的是let,其他部分声明方面和变量一样
let constA = 10
//constA =2 不能重新赋值
//数据输出
print(constA)
print("a的值是:\(a),f的值是:\(f)")//用\(变量的)形式插入到字符串输出
//整形
/// 默认的Int长度等于所在平台的原生字长,细分了Int8,16,32和Uint8,Uint16,32等等
//var uchar :UInt8 = 256 //范围是0-255 超出范围 报错了
var unchar :UInt8 = 0128 //前面加0也可以
var binaryInt = 0b1001_0100 //可以用二进制表示,支持下划线分开
var hexInt = 0xAf
var octalInt = 0o777 //这是八进制
//浮点数类型 1.十进制,2.科学技术法 5.2e3 = 5200 3.16进制数表示 0x5.a2p4, 以0x开头,p代表4
//的p次方 = 0x5.a2 * 2^4
//浮点数提供了正无穷大,负无穷大和非数 三个 特殊的浮点数。
//正的浮点数 除以0.0得到正无穷,负的浮点数除以0.0得到负无穷,0.0除以0.0的非数
var float_a = 5.0,float_b = -5.0
print("正无穷和正无穷相等\(float_a/0.0==(4.0/0.0)),负无穷和负无穷相等\(float_b/0.0==(-4.0/0.0)),非数和非数自己都不相等\(0.0/0.0==(0.0/0.0))")
//非浮点数除以0.0会报错的
//var int_num= 5
//int_num/0.0
//
//
//
//数据类型的转换,数据类型转换如果数值超出范围就会报错,swift属于强类型语言,不同类型的值经常需要转换
var t_a:UInt8=100
var t_b:UInt16=10
//类型不一样,直接编译出错
//t_a=t_b;
//t_b = t_a
t_b = UInt16(t_a)//强制转换时可以的
//Bool值只能用true和false,不能用0或非0 表示,其他类型的值也不转化为bool值。在该使用bool值的地方一定要用Bool
//这是不行的
//var i = 1
//if i
//{
// //
//}
//var i = true
//if i
//{
// //这是可以的
//}
//
//元组 :tuple 使用圆花括号把多个值复合成一个复合值,定义元组类型的变量
var people = ("zhangsan",14,170.00) //这是系统推断的方式
var book :(String,Float,Int)//可以事先声明
book = ("bookname",30.0,2)
print(book)
var test : (Int,(Float,String))//元组成员又是元组
test = (10,(100.0,"bookName"))
//元组访问
print(test.0)//可以通过点加下标的方式访问
print(test.1.0)
//元组的拆分
var (num,(price,name))=test
print("\(num),\(price),\(name)")
let (c_num,(_,c_name))=test //可以用下划线表示要忽略元素
//可以使用key:value的形式为每个元组内的变量指明名字
var health = (height:175,weight:65)//可以直接写值
var score : (swift:Int,name:String)//也可以后面直接跟这个变量类型声明
score = (80,"real") //不写指定值只能按照格式顺序
score=(name:"real",swift:100)//指定值可以打乱顺序.所以访问元组的数据也可以通过元组的变量名访问
print(score.name)
//可选类型 -
var str_val = "123"
var val1:Int? = Int(str_val) //.toInt这个方法找不到了,变成用构造器转换了不加?代码编译不过去,因为转换可能会失败。
//如果没有选择?,表示职能转换为Int,在转化失败的时候 属于『值缺失』,需要处理值缺失的时候即使nil
//Switf里面 nil和OC的不同,OC里面的nil表示一个不存在对象的指针,Swift里面的nil表示的是确定的值,表示值缺失
//只有可选类型的变量或常量才能接受nil,非可选的变量和常量不可以接受,一个可选类型没有初始化,则值就是nil
var option_a:String? = "1234"
// 强制解析 :可选类型的变量和普通类型的变量不是相同的类型。比如不能直接把Int?直接转换为Int,用!表示 已知该变量有值,请提起其中的值
var value:Int = Int(option_a!)!//------需要这样写才能把可选类型的字符串转化为整数!!!
var n1 :Int? = 100
var n2 :Int? = 50
let n3 = n1!+n2!
print(n3)
//强制解析必须是可选类型,并且里面确实有值才能成功,否则程序会出错,可以使用 if val!=nil 表示如果这个可选类型的变量不等于nil
//可选绑定 :用于判断可选类型的变量和常量是否有值,如果可选的有值就赋值给另一个临时的变量或者常量
//可以在if分支对可选类型的变量进行判断
var str :String!="1234"
if var tem = str//如果str的值为nil就不会去来这里了
{
print(tem)
}
else
{
print("不能解析")
}
//隐式可选类型
//除了在任意已有类型的后面加?表示可选类型外,还可以在后面加!表示可选类型
//Int!和Int?区别是,当程序需要获取Int?类型的变量或常量值时候必须在变量后面添加!执行强制解析,
//Int!不用
var aa :Int? = 100
var ab :Int! = 50
var cc :Int = aa!
var dd :Int=ab
//类型别名
//typealias 相当 typedef
//typealias myInt = Int
// 字符和字符串
//Character 表示单个字符 String 表示字符串,字符可以用单个字符,转义字符,"\u{n}"unicode编码表示 n表示
//1-8位16进制数
var chara:Character = "\u{2666}"
print(chara)
chara = "好"
str = "两个不是图片的星星✨✨"
//目前最新的swift countElement已经被改成了count
print(str.characters.count)
//插入字符串可以用字符串插值的方式
str = "前面插入了这些 \(str)"
//for char in str //无法编译、
//{
// print(char)
//}
//
var str_1 = "first✨
//var str_2 = "firsy"
//print(str_1==str_2)
//var hasPrefix:Bool = str_1.hasPrefix("first")//是否以特定的开头
//var hasSuffix:Bool = str_2.hasSuffix("sy")
//
访问字符串中的UNICODE码
print("这里是UTF8编码:能用UTF8表示的就显示一个数,不能用显示的就会输出多个,每个表示一个字节,分多个字节输出,星星用了226 156 168表示对")
for codeUnit8 in str_1.utf8//这里返回的是一个utf8View类型的值,是一个包含多个Utf8的值的集合
{
print(codeUnit8,terminator:" ")//现在改成这个了 不换行输出用这个语句
}
print("这里是UTF16编码:和UTF8类似,这里每个表示一个字节")
for codeUnit16 in str_1.utf16//这里返回的是一个utf8View类型的值,是一个包含多个Utf8的值的集合
{
print(codeUnit16,terminator:" ")//现在改成这个了 不换行输出用这个语句
}
这里一个表示4个字节 unicodeScalars返回的 UnicodeScalarView类型的值 包含一个或多个unicodeScalar的值
是一个21位的Unitcode码,需要用.value属性获得数值是一个 Uint 32
//for codeUnit32 in str_1.unicodeScalars//这里返回的是一个utf8View类型的值,是一个包含多个Utf8的值的集合
//{
// print(codeUnit32.value,terminator:" ")//现在改成这个了 不换行输出用这个语句
//
//}
}
study++;
//------------------------- 运算符
if study < 100
{
//%求余数运算符 , 可以对小数求余数,两个操作数都是整数不能对0求余,有一个是浮点数,第二个可以是0.0或0结果是非数,余数的正负只和和除数的正负相关。
//var mod = 7.5%1.2
//
//print(mod) // =0.3
//溢出运算符,如果希望程序只是对溢出的数据位进行截断,而不是导致错误,可以使用Swift提供的溢出预算符
//&(+ - * / %)
//var a :UInt8 = 255
//
//var b:UInt8 = 255+a //这样竟然可以
//
//a = a &* 6 //溢出后进行截断操作
//范围运算符 a...b [a b] a..<b [a b)
for var idx in 0...100 //(0..<100)
{
print(idx)
}
// 引用比较对象运算符 === 和 !==== 用来判断两个引用类型的变量是否指向同一个对象。,
// == 用来比较内容
var d1 = NSMutableArray();
var d2 = NSMutableArray();
//d1 == d2 但是 d1!===d2
//nil 合并运算符 "a??b" 用来在可选类型的变量a是否为nil,如果为nil就返回后者b的值,a和b的类型必须一致
//相当于 a!=nil?a!:b
}
study++ ;
if study < 100
{
//var a=10
//if a>0
//{
// print(a)//即使这里只有一句 也必须用括号括起来
//}
//switch不用加break,每一个switch必须包含一条语句
//不能这样
/**
* case 1:
case 2:
print();
但是可以这样
case 1,2:
print();
但是有的时候为了使用C语言里面的贯穿特性
可以使用fallthrough
*/
var num = 5;
switch num
{
case 5...10: //可以表示范围
print(num)
//fallthrough 加上这句话下面的就会执行
default:
print(num+1)
}
var point:(x:Int,y:Int);
point = (50,50)
//(0,0)可以匹配到下面三个,遇到第一个就跳出,所以应该范围小的条件放在前面
switch point
{
// case (x:0,y:0): //(0,0) 也可以这样,
// print("位于原点")
// case (_,0)://元组里面可以匹配范围
// print("x轴>")
// case (0,_):
// print("位于Y轴")
case (0...100,0..<100):
print("在第一象限")
//default :
// break;
// case (50,var y)://把元组的匹配的值放入变量y里面
// print(y);
//case let d : //可以把switch的条件放到 变量或者常量中,如果希望在这里更改就用变量。这里let d 这语句可以匹配所有的情况所以可以替代default
case var(x, y) where x > 0&&y>0: //在case里面可以进行再次筛选
print("第一象限--》")
default:
break;
}
//case的值
print(point)
//循环结构
//var cnt = 10
//while cnt < 20
//{
// print(cnt)
// cnt++
//}
//do
//{
// cnt++
//}while cnt<30
for idx in 0 ..< 3 //for循环
{
print(idx)
}
for var a=0,b=0;a<0&&b<100;a++,b+=10//多个条件初始化
{
print(a,b)
}
//for ;; 死循环
//{
//
//}
//for in 用于遍历字符串,范围,序列和集合等包含的元素 这里的常量无需声明
/**
* for 常量名|_ in 字符串|范围|集合
*/
var friend = "myfriend"
for /*char*/_ in friend.characters //friend.characters 是最新的,原来只要写friend就行
{
// print(char)
print("kkk")//可以用 "_"来表示常量名,在不需要真正的遍历内容的时候可以用"_"
}
//这里的outer是一个标签,可以跳出到最外层的循环,有点类似于C语言的go语句,但是swift里面的标签只有放在循环
//开头出才有用,就像下面这样
outer:for i in 0 ..< 10
{
inner: for j in 0 ..< 10
{
print(i*j)
if i*j==4
{
break outer
}
if j==7
{
continue//不会跳出循环
//continue outer 这里也可以跟一个标签。忽略标签所指定的循环中剩下的语句,默认是inner
}
}
//continue outer发生后后这里的代码不会执行
}
}
// ----------------------------------- 4.集合
//var myArrs :Array<String>;//这里是声明,还不能用'
//
//
//var myArr2:[Int]
//这是构造器初始化
var myArr = Array<String>();//需要这样才能用
myArr.append("one")
myArr+["two"] //可以这样 写加入元素
var myArr2 = Array<String>(count: 10, repeatedValue: "ones")//可以这样
//这里是简化语法初始化
var b = ("books",15);
var values = ["a","b","c"]
//访问数组的元素可以使用下标
print(values[0])
values.count//数组的个数
for element in values
{
print(element)
}
values .insert("d", atIndex: 0)
//数组的可变性和可修改性完全取决于是用let还是var
//数组的下标可以是范围
values[0...1]
//多维数组
var secArr :[[Int]] //一个Int类型的二维数组
secArr = Array<Array<Int>>(count: 4, repeatedValue: [])//表示最外层的数组装了四个一维数组
secArr[0] = Array<Int>(count: 5, repeatedValue: 1)
//----这样的循环过时了,不知道怎么写
for var i = 0,len = secArr.count;i<len;i += 1
{
for var j = 0,len2 = secArr[i].count;j<len2;j += 1
{
print(secArr[i][j])//遍历每个数组内的数组元素
}
}
//
var n = 4
var drawArr = Array<Array<Int>>(count: n, repeatedValue: []);//声明一个二维数组
for i in 0 ..< n
{
drawArr[0] = Array<Int>(count: n, repeatedValue: 0)
}
drawArr[0].append(10)
drawArr.removeLast();
var i = 0,j = 0, cur_pos = 1
var start = 0;
drawArr[0]
//-------字典 键和值用冒号隔开
var mydic:Dictionary=["key1":"value1","key2":"value2"]
//声明语法
var scores:Dictionary<String,String> //这里是逗号,
var scores2:[String:String] //这里是冒号:
//泛型创建字典
var scores3:Dictionary<String,Int>
scores3 = Dictionary(minimumCapacity: 5)
//updateValue会返回一个字典内value的可选类型的值(?),如果原来的键值对不存在
//就返回nil
scores3.updateValue(100, forKey: "math")
scores3["chinese"]=90
scores3["english"]=80
for (item,score )in scores3// 前面是键后面对应的是值
{
print(item,score)
}
var keys = Array(scores3.keys)//必须用Array构造器
scores3.count
//字典的删除
scores3.removeAll();
//集合的复制,包含的数据是值类型复制副本,引用类型复制指针
var arr_ori = ["one","two","three"]
var arr_cp1 = arr_ori;
var arr_cp2 = arr_ori
arr_cp1[0]+="1"
arr_cp2[0]+="2"
print(arr_cp1[0])
print(arr_cp2[0])
//引用复制
class User: NSObject {
var name:String
init(name:String) {
self.name = name
}
}
var UserOri = [User(name: "wokong"),User(name: "bajie")]
var user1=UserOri;
var use2=UserOri
user1[0].name="oo"
use2[0].name="d"
---- 5--------------------- 闭包和函数
study+=1;
swift 不仅仅是面向对象的语言
/*
func 函数名(形式参数列表)[->返回值类型]
{
}
*/
func max(x:Int,y:Int) -> Int {
return x>y ? x:y
}
//支持多个返回值,需要元组的辅助
func getmessage(person:String) -> (String,String) {
return ("test","100")
}
getmessage("mine")
//也可以指定元组的返回参数
func getmessage2(person:String) -> (name:String,height:String) {
return ("test","100")
}
var msg = getmessage2("test")
print(msg.height,msg.name) //可以通过属性访问
//递归函数
func fn(i:Int) -> Int {
if i==1 {
return i
}
else
{
return i*fn(i-1);
}
}
//fn(<#T##i: Int##Int#>) 这样只有数据类型不直观
print(fn(5))
//函数的形式参数 name和 msg都是参数
func sayHi(user name:String,msg:String) {
print("程序正在执行sayHi()函数")
print("\(name),\(msg)")
}
//sayHi(user: <#T##String#>, msg: <#T##String#>);// 指定参数名
//用局部形参名做形式参数名 ----- 这里是swift修改了
//
//func sayHI2(#name:String) -> Void {
//
//
//}
//形参默认值,有默认值的话调用的时候可以省略形参,一般把带有默认值的放在后面。
func say2(user name:String="孙悟空") -> String {
return name
}
print(say2());
//个数可变的形参,允许指定数量不确定的形参。在最有一个形参的类型后增加 ... 表示可以接受多个参数值,多个参数值被当成数组传入
func test(a :Int,books:String...) -> Void {
for tmp in books {
print(tmp)
}
}
test(10, books: "OC","swift")
//常量形参和变量形参,形参函数默认的是常量,在函数内不能对参数列表的形参进行修改,如果需要直接使用形式参数做变量,而不需要在函数内重新定义,需要用var
//声明函数形参
//这里用var修饰已经提示过期了,就是参数就是不可修改的
func test2(/*var*/ width:Double,height:Double) -> Void {
// width = 100;
// 现在苹果不能用var修饰了
}
// in out形参,用inout关键字声明的形参可以进行传递真实的值,不是副本,类似于
//C语言的传地址,这里是可以修改的
func test3(inout a:Int,inout b:Int) -> Void {
a = a-b
}
//print(test3(&<#T##a: Int##Int#>, b: &<#T##Int#>)) 打出来就是这个样子的
var s_a = 3,s_b=4;
test3(&s_a, b: &s_b)
print(s_a)
// 函数类型 --- C语言里面的函数指针
var p = test3; //可以直把函数赋值
var pType:(Int,Int)->Int
pType = max;
//函数类型做为参数
func fuc(a:Int,b:Int,p:(Int,Int)->Void) -> Void {
p(a,b);
}
//函数重载,可以定义多个同名函数,但是要形式参数或者返回值不相同。
//函数的嵌套。默认的函数是全局的,嵌套在函数内的函数,在内部有效,可以通过
//前面的函数类型的返回值,返回具体的内容函数供外部调用
//----------------嵌套函数和闭包 ,闭包类似于Objective -C 里面的代码块
//-- 全局函数是一个有名称,但是不会捕获任何值的闭包。嵌套函数是一个有名字
//可以捕获封闭函数体的值的闭包,闭包表达式是一个简洁的,可以捕获封闭函数体的值的匿名闭包
//定义闭包
func getMathFunc(type:String) ->(Int)->Int {
switch type {
case "square":
return{ (val:Int) ->Int in //闭包 ,放在一个大括号内,没有func关键字和函数名字
return val*val
}
case "cube":
return{ (val:Int) -> Int in
return val*val*val;
}
default:
return {
(val:Int) -> Int in
var t = 0;
for i in 0...100
{
t+=i;
}
return val*t;
}
}
}
var mathFunc = getMathFunc("cube");
print(mathFunc(5));
//省略形参名。闭包表达式可省略,返回值的情况下,关键字 in也可以省略,闭包表达式可以通过$0,$1,$2来引用第一个,第二个。。。形参
//尾随闭包
//函数的参数类型是函数类型和闭包类型是相同的,可以传递闭包也可以传递函数
func someFunction (val:Int,fn:(Int)->(Int))->(Int)
{
//执行代码
return fn(val)
}
var sqare = { (val:Int)->Int in
return val*val;//闭包只有一行代码,return 关键字
}
print(someFunction(10, fn: sqare))
//这是普通闭包
someFunction(20, fn: {//放的是执行体
(val:Int)->Int in
return val*val;//闭包只有一行代码,return 关键字
})
//这里是尾随闭包
someFunction(20)//闭包表达式在花括号的外面
{
(val:Int)->Int in
return val*val;//闭包只有一行代码,return 关键字
}
//闭包捕获上下文的变量和常量,可以修改上下文中的常量和变量,即使定义这些变量和常量的作用域不存在了,也可以访问和修改????
func makeArray(ele:String)->()->[String] //返回的是一个没有参数,返回值为String的函数
{
var arr:[String] = []
func addElement()->[String]
{
arr.append(ele)
return arr
}
return addElement
}
//这注意
let add1 = makeArray("one")
print(add1())
print(add1())
let add2 = makeArray("two")
print(add2())//add2h额add1没有关系
//闭包是引用类型
var add3 = add2 //add3 直接更改值
print(add3())
//------ 面向对象上,除了定义自定义类还有枚举,结构,类。都支持定义存储属性,计算属性,方法,下标,高早起和嵌套类型
//------上面这句话暂时理解不了,信息量有点大呀。。。 说支持所有的类型。类,结构体,枚举这三种程序单元的内容分别可以定义属性(存储属性和计算属性),方法,下标,构造器和嵌套类型(嵌套类,嵌套结构体,嵌套枚举)
//5种类型的成员,这5种成员在类,结构体,枚举各有区别
//-- 定义枚举
enum Season
{
case Spring // case 关键字
case Summer
case Fall
case Winter
//case one,two 这样也是可以的
}// 这里没有给分配一个默认的整数值。枚举名就代表了一个实例。和整数没有任何关系
//定义了swift任意类型后,以下几方面使用
/*
1.声明变量
2.创建实例
3.访问类型属性
4.调用类型方法
5.派生子类
*/
//声明变量
var sn :Season;
sn = Season.Spring//可以直接用枚举的实例赋值
switch (sn)
{
case .Spring:
print("spring")
case .Summer:
print("summer")
default :
print("default")
}
enum enum2:Int
{
case one,two=3,three //one = 0.three = 4
}
enum enum3:Character {
case one = "O"
}
//要么不指定,要么全部都必须确定有值,指定属性可以使用构造器的属性
var day = enum2.init(rawValue: 3);//根据值获取枚举值,可能失败的构造器
var day2 = day?.rawValue
//枚举的关联值
//case 枚举值 (元组语法)
enum Planet
{
case Earth(Double,String)
case Mars(density:Double,name:String)
case Sun
}
var p1 = Planet.Earth(1.0, "地球")
var p2 = Planet.Mars(density: 2.0, name: "火星")
switch(p2)
{
case Planet.Earth(var weight,var name): //真是奇葩,可以这样关联
print(weight,name)
default:
break;
}
//类和结构体
/*
区别:
1结构体不支持继承
2.不支持自定义构造器
3.结构体是指类型,不是引用类型
*/
//swift的属性分为 存储属性(实例变量)和计算属性(相当于property合成的属性)
//class表示一个属性或者方法是否属于类,static 用于结构体和枚举相当于类里面的class
class person: NSObject {
var name:String=""//必须初始化。
var age:Int=0 ;
func say() -> Void {
print("\(name) -- \(age)")
}
func say(message:String) -> Void {//函数 持重载
print("\(message)")
}
func growp(a:Int) -> person {
age+=a
return self
}
// init(n:String,a:Int) {//显示 定义带参数的构造器,没有自定义系统会提供一个默认的
//
// self.age=a;
// self.name=n
// }
}
var per1 = person();
per1.name = "P1"
per1.age = 0;
per1.say()
per1.say("消息")
var per2 = person()
per2.name="P1"
per2.age=0;
//===判断应用类型,==比较值类型,可以重载==号,自己定义比较类型
func ==(p1:person,p2:person) -> Bool {
if p1.name==p2.name&&p1.age==p2.age {
return true
}
return false
}
print(per2==per1)
per1.growp(1).growp(2) //这里类似于OC里面的链式编程
//存储属性-- 存储在类,结构体,枚举内部的常量或者变量。
struct FixedLengthRange {
var start:Int
//定义常量存储属性
let length :Int
//系统会为 "结构体" 提供所有存储属性的构造器,所以可以不指定初始值
}
var rg = FixedLengthRange(start: 2, length: 3);
//rg.length=0 初始化后就不能改
class lazyC: NSObject {
lazy var tem = 100//懒加载关键在,类似于OC里面的重写get方法里面初始化,通过.语法访问才初始化
}
//计算属性 property属性,实例计算属性和类计算属性
enum XBSeanon :Int{
case Spring,Summer,Fall,Winter
//info就是计算属性
var info:String{
//在这里写get和set方法
get{
switch self { //去掉get方法就是只读属性
case .Spring:
return "春"
default:
return "非春天"
}
}
set(newValue)//这个形参可以省略,
{
if newValue=="春天" {
self = .Spring
}
else
{
self = .Summer//瞎写测试
}
}
}
mutating func changeV() //mutatiing 表示可变,用在结构体和枚举
{
self = XBSeanon(rawValue: (self.rawValue+1)%3)!
}
}
//var mys = XBSeanon.Spring
//print("\(mys.info)")//get
//mys.info = "春天"
属性观察者。类似于KVO或者重写set方法实现的功能
class User {
//这里的属性观察没有什么意义,因为没有重写setter方法和getter方法,对属性赋值操作检查应该在set方法做检查,
var name :String = "" {//不能监听懒加载的熟悉
willSet{
//这里放的是属性赋值前,自动要执行的代码
if newValue.characters.count<3 {
print("小于3")
}
}
didSet
{
print("已经设置成功了")
}
/*
get
{
return "success"
}
set {
self.name = "fail" set和get代码和上面的不能共存,set个get要求没初始化,willSet和didSet应
}
}*/
}
func move(x:Int)
{
}
}
var U = User()
U.name="1"
U.name
//属性和方法统一
//可以直接函数类型定义存储属性,并将函数和闭包传递就行
//下标
struct FKRect {
var x:Int
var y:Int
var width:Int
var heigth:Int
subscript (idx:Int) ->Int //输入参数不支持指定外部参数,返回值可以返回任意类型,数组就是下标,字典就是value的类型
{
get{
//定义一段可执行的代码,
switch(idx)
{
case 0:
return self.x
case 1:
return self.y
case 2:
return self.width;
case _ :
return self.heigth
}
}
set
{
switch (idx)
{
case 0:
self.width = newValue
default:
self.heigth = newValue
}
}
}
//int 是访问的形式,可以是字符串,联想字典 dict[@"one"];
subscript (idx:Int) -> String //输入参数不支持指定外部参数,返回值可以返回任意类型,数组就是下标,字典就是value的类型
{
get{
//定义一段可执行的代码,
switch(idx)
{
case 0:
return "width"
case 1:
return "height"
case 2:
return "x"
case _ :
return "y"
}
}
set
{
switch (idx)
{
case 0:
self.width = 12
default:
self.heigth = 123
}
}
}
}
var rect = FKRect(x: 0, y: 0, width: 100, heigth: 100)
rect[0]=100 //通过下标引用
var num:String = rect[0]
print(rect.width)
//--------------------------可选择链
//可选链代替强制解析
class BOOK {
var bookName:String!
init(name:String)
{
self.bookName = name
}
}
class Student {
var book:BOOK!
}
class School {
var stu:Student!
}
var school = School()
//print(school.stu.book)// 这样写就错了。可以把!换成?作为可选链。!表示隐式解析,?表示可选链。中间有一个为nil就会返回nil,不会继续向后执行。
print(school.stu?.book)
//可选链 适用于 属性,方法,下标
//-----类属性和类方法 (枚举,类,结构体自身的方法)
//--值的类型属性包含枚举和结构体,用static修饰,包含存储属性和计算属性。“”“”类的类型属性只能定义计算属性“”“”“”“
//构造器---无须显示的声明返回值类型,无须显示的使用return返回实例,名字都是init函数,可以有多个函数重载
/**
* 对于结构体提供两个构造器,无参数的和初始化所有的。对于类提供了无参数的。需要自定义的时候就自定义,自定义后就不在提供默认的
构造器的外部参数和局部参数相同--swift做的。
*/
class TestInit {
var name:String?
let const = 10
//
// init(_ n:String)
// {
// self.name = n
// //self.const = 100//这里是不能被修改的。据课本上说原来是可以的
// }
//构造器也可以重载
//可能失败的构造器,
init?(_ n:String)//可能失败的构造器
{
if n.characters.count<1 {
return nil
}
}
}
//var testI = TestInit.init(n: "a")
var testII = TestInit.init("A")//隐藏外部参数名字
//可能失败的构造器传播:可能失败的构造器可以调用同一个类中的普通构造器,普通构造器不能调用同一个类中可能失败的构造器,但是在结构体中普通的可以调用可能失败的。
class M1 :TestInit{
var grade:Int!
init!(name:String,grade:Int)
{
super.init(name)//可能失败的调用 正常的
}
}
class M2 :M1{
var grade2:Int!
// override init(name:String,grade:Int) //普通的不能调用可能失败的。
// {
// // super.init?(name: name, grade: grade)//可能失败的调用 正常的
// }
}
//------------------------------------- 面向对象下
//********重写父类的属性,下标,观察者貌似全部更改了********/
//子类重写父类的属性
class brid {
static var speed:Double = 0
}
// ----- 变了----
//var eagle:brid
//{
// var speed:Double{//重写父类的属性 //现在改了,不能这样写了。只能
//
// get{
// print("正在访问被重写的属性")
// }
// set{
// super.speed = 100
// }
// }
//}
//var eagle:brid
//{
// var speed:Double{//重写父类的属性 //现在改了,不能这样写了。只能
// get{
// print("正在访问被重写的属性")
// }
// set{
// super.speed = 100
// }
// }
//}
//--final 可以修饰类,属性,方法和下标,防止被集成,重写,
final class Base
{
final var name :String=""
final func say (content:String)
{
print("Base对象说\(content)")
}
}
//类的构造和析构
class Apple {
var name:String!
var weight:Double
init(name:String,weight:Double)//制定构造器,1个或者多个,完成所有的属性初始化,可以调用父类的制定构造器,如果有父类,必须调用父类的init
{
self.name = name;
self.weight = weight
}
convenience init(n:String)//便利构造器
{
self.init(name:n,weight: 100)//必须调用其他构造器 ,或者最终调用的是指定构造器
self.name = "xiugaile "
}
}
//多态
class baseClass
{
func test()
{
print("基类的方法")
}
}
class subClass:baseClass
{
override func test() {
print("这是子类")
}
}
class subClass2:baseClass
{
override func test() {
print("这是子类2")
}
enum type
{
case height,low
}
}
var instant:baseClass = subClass();
instant.test();//这里执行的其实是子类
//is运算符检验类型 相当于 isKindOf isMemberOf
print("\(instant is subClass)")
//as运算符向下转型
var instant2 = instant as? subClass2//类型强制转换,可能失败
//两个不确定的类型特殊类型
var arr:[Any] = ["one",1] //any表示任意类型,anyobject表示任意对象
// -- 扩展
extension String
{
//扩展方法
func XBLength(Str:String) ->Int
{
return Str.characters.count;
}
}
// -- 协议
@objc protocol Draw //可选类型要有objc符号
{
@objc optional
var drawCirle:Double{get set};//属性
func drawCubic(width:Double);//方法
}
class SwitftDraw:Draw
{
@objc var drawCirle:Double
{
get{
return self.drawCirle;
}
set
{
self.drawCirle = newValue;
}
}
@objc func drawCubic(width: Double) {
print("立方体 \(width)")
}
}
//泛型 类型占位符
func copyArray <T> (src:[T],inout dest:[T])
{
for element in src
{
dest.append(element)
}
}
//这个方法可以复制任意类型的数组
//可以定义多个不同的参数
func projection<SrcType,DesType>(src :[SrcType],fn:(SrcType)->DesType) ->[DesType]
{
var result = [DesType]();
for element in src
{
result.append(fn(element));
}
return result;
}
var books = ["C和指针","算法导论"]
var proj = projection(books){
$0.characters.count
}
//类也可以使用泛型
class AppleS<T:Comparable>//这里通过协议对泛型进行限定
{
var info:T
init(info:T)
{
self.info = info
}
}
extension AppleS
{
//扩展类可以直接使用泛型
func bigThan(other:AppleS,fn:(T,T) ->Int) ->Bool {
if fn(self.info,other.info)>0
{
return true;
}
else
{
return false;
}
}
}