下面简单的介绍结构体这一自定义数据类型的应用
计算属性
类型属性
类型方法
属性观测器
延迟属性
访问控制
单例模式初探
struct Point {
var x = 0.0
var y = 0.0
}
struct Size {
var height = 0.0
var width = 0.0
}
class Rectangle {
var origin = Point()//这个就好像origin是结构体的一个变量名,但是结构体又是类的属性
var size = Size()
var ddd = String()
var ss :Size//注意:如果要将类中的属性,以结构体为例,那么有两种写法,第一种写法是属性后面加上:type。第二种写法是属性后面加上=type()
//计算型的属性必须声明为var,因为它是一个变量,这里应该注意计算下属性的结构
var center: Point{
get{//这里表面取center的时候调用
let centerX = origin.x + size.width / 2
let centerY = origin.y + size.height / 2
return Point(x: centerX, y: centerY)//这里返回的是一个点,返回的是Point结构体的初始化一样
}
set{//这里表明给center赋值的时候调用,newCenter是传递进来的值,当然也可以使用系统默认的newValue
origin.x += newValue.x - center.x
origin.y += newValue.y - center.y
}
}
var area: Double{//这里记住get必须要有一个返回值,就像center属性一样,放回的是Point类型,这里放回的是double类型
get{
return size.height * size.width
}
}
// 这句话报错的原因是:如果一个计算属性有set方法,就必须要有get方法,而且计算属性一定要指明数据类型
// var sss: Double{
//
// set{
//
//
//
//
// }
//
//
// }
init(origin: Point , size: Size ,ss: Size){
self.origin = origin
self.size = size
self.ss = ss
}
}
//这个有点像frame的设计思想,这句话的意思是:通过init构造函数初始化类,
var rect = Rectangle(origin: Point(x: 0, y: 0), size: Size(height: 20, width: 19), ss: Size(height: 20, width: 20))
rect.origin = Point(x: 10, y: 10)
rect.center
rect.center = Point()//将中心点的位置设置为0,0
rect.center
rect.area
Int.max//这就是类型的属性,将类型方法或者属性定义在类型上
Int.min
class Player {
var name: String
var score = 0
//现在我有个需求,就是想有一个最大的分值,这样我就需要将这个最大的分值属性定义在类型上,使用static关键字修饰,使得hightestScore这个属性不会因为再次调用类的时候初始化
static var hightestScore = 0
init(name: String){
self.name = name
}
func play() {
let score = random()%100 //注意:score是局部变量
print("\(name) play the game and get \(score) score")
self.score += score
print("the total score of \(name) is \(self.score) score")
if self.score > Player.hightestScore{
Player.hightestScore = self.score
}
//这样就在这个类上定义了一个最高分
print("the hightest score is \(Player.hightestScore)")
}
}
var play = Player(name: "yhy")
var play2 = Player(name: "yhy1")
play.play()
play.play()
play.play()
play2.play()
play2.play()
play2.play()
struct Matrix{
var m: [[Int]]
var row: Int
var col: Int
init?( _ arr2d:[[Int]] ){
guard arr2d.count > 0 else{
return nil
}
let row = arr2d.count
let col = arr2d[0].count
for i in 1..<row{
if arr2d[i].count != row{
return nil
}
}
self.m = arr2d
self.row = row
self.col = col
}
static func identityMatrix(n: Int) -> Matrix?{
if n <= 0{
return nil
}
var arr2d:[[Int]] = []
for i in 0..<n{
var row = [Int](count: n, repeatedValue: 0)
row[i] = 1
arr2d.append( row )
}
return Matrix(arr2d)
}
func printMatrix(){
for i in 0..<row{
for j in 0..<col{
print(m[i][j],terminator:"\t")
}
print()
}
}
}
let m = Matrix([[1,2],[3,4]])!
m.printMatrix()
let e = Matrix.identityMatrix(6)!
e.printMatrix()
//property observer
//属性观察器就是willSet和didSet,但是,需要特别强调的是,虽然当属性的值发生变化的时候,就会执行willSet和didSet大括号里面的语句,但是如果是构造方法的赋值,就不会执行willSet和didSet大括号里面的语句,这点要注意
class LightBulb {
static let maxCurrent = 30
var current = 0{
//观察属性和计算属性一样,如果你不想给以前的值或者新值取名字的话,可以使用newValue和oldValue
willSet{//willSet会将要赋值的时候执行,那么将要赋值的时候,我们可以做一些操作
print("the change is \(abs(current - newValue))")
}
didSet{//didSet表示已经将current进行了赋值,在didSet后面写上(oldCurrent)表示还没有赋值以前的值,大括号里,可以拿到已经进行赋值的值,也可以拿到赋值之前的oldCurrent的值
if current == LightBulb.maxCurrent {
print("that is the max")
}else if current > LightBulb.maxCurrent {
print("that is over the max")
current = oldValue
}
print(current)
}
}
}
let bulb = LightBulb()
bulb.current = 20
bulb.current = 30
bulb.current = 40
bulb.current = 59
//lazy property(懒加载属性)
class ClosedRange{
let start: Int
let end: Int
var width: Int {
get{
return end - start + 1 //注意在swift的语法中呢,变量和运算符一定要隔开一个空格
}
}
//现在我有个需求,想计算出start到end之间所有数的和,并且用到它的时候再调用,那么我将这个属性设置为懒加载属性
//这个懒加载属性用“=”号连接一个闭包的函数,所以在{}后面还有加上(),那么我们在这里用到这个属性的时候就会调用这个属性的{}里面的内容,而且调用了之后,这个属性的值就会存储起来,下次调用的时候,就不会再次执行{}里面的内容了
lazy var sum :Int = {
print("sum")
var tmp = 0
for i in self.start...self.end{
tmp += i
}
return tmp
}()
init?(start: Int, end: Int){//可能构造函数返回的是一个控制,所以使用可选型
if start > end {
return nil
}
self.start = start
self.end = end
}
}
if let closedRange = ClosedRange(start: 0, end: 10_000){
closedRange.width
closedRange.sum
closedRange.sum
closedRange.sum
}
/*访问控制
*
*1.public:可以被模块外访问
*
*2.internal:可以被本模块访问
*
*3.private:可以被本文件访问
*
*/
/*单例设计模式初探(由于需要用到两个文件,这里就不上代码了!!!)
*在这个例子中,一个类被外界访问之后,当拿到这个类的时候,就会重新调用这个类的初始化方法,那么这个类中的原有属性将再初始化,为了避免这个现象,我们可以将这个类中的初始化函数设置为private,现在当外界调用这个类的时候,就不能够初始化就会报错,好吧,那么作为一个类他会这么想,如果别人不能够初始化我,我就自己初始化自己吧,那么我们就可以在这个类里面定义一个变量,用这个变量来调用这个类,并且在属性前面加上一个static关键字,和public关键字,这样一来呢,这个变量就变成了一个类型属性,在外面,我们就可以直接用这个类拿到这个类型属性,就相当于初始化了这个类,问题解决了,好开心!!!
*/