属性和常量

如果创建了一个结构体的实例并赋值给一个常量,则无法修改实例的任何属性:

let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
rangeOfFourItems.firstValue = 6
  • 当值类型的实例被声明为常量的时候,它的所有属性也就成了常量
  • 当引用类型的实例赋给一个常量后,仍然可以修改实例的变量属性。

延迟属性

  • 属性声明前使用@lazy来标示一个延迟存储属性。
  • 延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性
  • 必须将延迟存储属性声明成变量(使用var关键字),因为属性的值在实例构造完成之前可能无法得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。
什么时候使用延迟属性?
当属性的值依赖于在实例的构造过程结束前无法知道具体值的外部因素时
当属性的值需要复杂或大量计算时,可以只在需要的时候来计算它
class DataManager {
@lazy var importer = DataImporter()
var data = String[]()
// 这是提供数据管理功能
}

计算属性:getter和setter

如果计算属性的 setter 没有定义表示新值的参数名,则可以使用默认名称newValue。
必须使用var关键字定义计算属性,包括只读计算属性,因为它们的值不是固定的。let关键字只用来声明常量属性,表示初始化后再也无法修改的值。

struct Rect{

    var _center:String;

    var center: String {
get {
return _center;
}
set (newCenter){
_center = newCenter
}
} } //使用newValue
struct Rect2{ var _center:String; var center: String {
get {
return _center;
} set{
_center = newValue
}
} }

属性观察器

  • 属性观察器监控和响应属性值的变化,每次属性被设置值的时候都会调用属性观察器,甚至新的值和现在的值相同的时候也不例外。
  • 可以为除了延迟存储属性之外的其他存储属性添加属性观察器,
  • 不需要为无法重载的计算属性添加属性观察器,因为可以通过 setter 直接监控和响应值的变化。
  • 可以通过重载属性的方式为继承的属性(包括存储属性和计算属性)添加属性观察器

属性观察器:

  • willSet在设置新的值之前调用,willSet观察器会将新的属性值作为固定参数传入,在willSet的实现代码中可以为这个参数指定一个名称,如果不指定则参数仍然可用,这时使用默认名称newValue表示。
  • didSet在新的值被设置之后立即调用,didSet观察器会将旧的属性值作为参数传入,可以为该参数命名或者使用默认参数名oldValue。
  • willSet和didSet观察器在属性初始化过程中不会被调用,它们只会当属性的值在初始化之外的地方被设置时被调用。
  struct Test{
var test:Int = 0{
willSet {
println(newValue)
}
didSet{
println(oldValue)
}
}
}
var a = Test();
a.test = 5;

全局变量,局部变量和延迟属性,计算属性,属性观察器

全局或局部变量都属于存储型变量,跟存储属性类似,它提供特定类型的存储空间,并允许读取和写入。

  • 在全局或局部范围都可以定义计算型变量和为存储型变量定义观察器,计算型变量跟计算属性一样,返回一个计算的值而不是存储值,声明格式也完全一样。
  • 全局的常量或变量都是延迟计算的,跟延迟存储属性相似,不同的地方在于,全局的常量或变量不需要标记@lazy特性。 局部范围的常量或变量不会延迟计算。
var test:Int = 0{
willSet {
println(newValue)
}
didSet{
println(oldValue)
}
} test = 5 ; var str:String{
get{
return String(test);
}
set {
test = newValue.toInt()!+5
}
}
println(str);
str = "4";
println(str)

类型属性---静态属性

使用关键字static来定义值类型的类型属性,关键字class来为类(class)定义类型属性:

struct SomeStructure {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
// 这里返回一个 Int 值
}
} enum SomeEnumeration {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
// 这里返回一个 Int 值
}
} class SomeClass {
class var computedTypeProperty: Int {
// 这里返回一个 Int 值
}
}

类型属性是通过类型本身来获取和设置,而不是通过实例。

println(SomeClass.computedTypeProperty)
// 输出 "42" println(SomeStructure.storedTypeProperty)
// 输出 "Some value."
SomeStructure.storedTypeProperty = "Another value."
println(SomeStructure.storedTypeProperty)
// 输出 "Another value.”

self 和 parent

  • 类型的每一个实例都有一个隐含属性叫做self,self完全等同于该实例本身
  • 你不必在你的代码里面经常写self。不论何时,只要在一个方法中使用一个已知的属性或者方法名称,如果你没有明确的写self,Swift 假定你是指当前实例的属性或者方法
  • 使用这条规则的主要场景是实例方法的某个参数名称与实例的某个属性名称相同的时候。在这种情况下,参数名称享有优先权,并且在引用属性时必须使用一种更严格的方式。这时你可以使用self属性来区分参数名称和属性名称。
  • 变异方法能够赋给隐含属性self一个全新的实例。
  • 在类型方法的方法体(body)中,self指向这个类型本身,而不是类型的某个实例。对于结构体和枚举来说,这意味着你可以用self来消除静态属性和静态方法参数之间的歧义
  struct Point {
var x = 0.0, y = 0.0
mutating func moveByX(deltaX: Double, y deltaY: Double) {
self = Point(x: x + deltaX, y: y + deltaY)
}
} enum TriStateSwitch {
case Off, Low, High
mutating func next() {
switch self {
case Off:
self = Low
case Low:
self = High
case High:
self = Off
}
}
}
var ovenLight = TriStateSwitch.Low
ovenLight.next()
// ovenLight 现在等于 .High
ovenLight.next()
// ovenLight 现在等于 .Off

变异 mutating

  • 结构体和枚举是值类型。一般情况下,值类型的属性不能在它的实例方法中被修改。
  • 要使用变异方法, 将关键字mutating 放到方法的func关键字之前
  • 不能在结构体类型常量上调用变异方法,因为常量的属性不能被改变,即使想改变的是常量的变量属性也不行
  struct Point {
var x = 0.0, y = 0.0
mutating func moveByX(deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveByX(2.0, y: 3.0)

实例方法

  • 实例方法能够隐式访问它所属类型的所有的其他实例方法和属性。
  • 实例方法只能被它所属的类的某个特定实例调用。
  • 实例方法不能脱离于现存的实例而被调用。

Swift 中方法的名称通常用一个介词指向方法的第一个参数,比如:with,for,by等等。
关于方法的外部参数:

  • Swift 默认仅给方法的第一个参数名称一个局部参数名称;默认同时给第二个和后续的参数名称局部参数名称和外部参数名称。
  • 可以自己添加一个显式的外部名称或者用一个井号(#)作为第一个参数的前缀来把这个局部名称当作外部名称使用。
  • 如果你不想为方法的第二个及后续的参数提供一个外部名称,可以通过使用下划线(_)作为该参数的显式外部名称,这样做将覆盖默认行为。
class Counter {
var count: Int = 0
func incrementBy(amount: Int, numberOfTimes: Int) {
count += amount * numberOfTimes
}
} let counter = Counter()
counter.incrementBy(5, numberOfTimes: 3)

类型方法--静态方法

声明类的类型方法,在方法的func关键字之前加上关键字class;声明结构体和枚举的类型方法,在方法的func关键字之前加上关键字static。

struct LevelTracker {
static var highestUnlockedLevel = 1
static func unlockLevel(level: Int) {
if level > highestUnlockedLevel { highestUnlockedLevel = level }
}
static func levelIsUnlocked(level: Int) -> Bool {
return level <= highestUnlockedLevel
}
var currentLevel = 1
mutating func advanceToLevel(level: Int) -> Bool {
if LevelTracker.levelIsUnlocked(level) {
currentLevel = level
return true
} else {
return false
}
}
}

swift 属性和方法的更多相关文章

  1. Swift的属性,方法,下标脚本以及继承

    从这篇章节起,Swift编程语言指南大部分的重要内容在于概念,代码并非太多.理解Swift的面向对象理念,语法以及类结构,构造析构过程对于非常好的应用Swift语言将会有比較大的帮助. 属性 存储属性 ...

  2. 李洪强iOS开发Swift篇—10_方法

    李洪强iOS开发Swift篇—10_方法 一.简单说明 跟其他面向对象语言一样,Swift中的方法可以分为2大类: (1)实例方法(Instance Methods) 在OC中,实例方法以减号(-)开 ...

  3. 我的Python学习笔记(四):动态添加属性和方法

    一.动态语言与静态语言 1.1 动态语言 在运行时代码可以根据某些条件改变自身结构 可以在运行时引进新的函数.对象.甚至代码,可以删除已有的函数等其他结构上的变化 常见的动态语言:Object-C.C ...

  4. swift 学习- 12 -- 方法

    // 方法 是与某些特定类型相关的函数.  类, 结构体,枚举 都可以定义实例方法, 实例方法为给类型的实例封装了具体的任务与功能.  类, 结构体, 枚举 也可以定义类型方法,  类型方法与类型本身 ...

  5. Swift 学习笔记 (方法)

    方法 是关联了特定类型的函数.类,结构体以及枚举都能定义实例方法,方法封装了给定类型特定的任务和功能.类,结构体和枚举同样可以定义类型方法,这是与类型本身关联的方法.类型方法与 Objective-C ...

  6. PHP 面向对象编程和设计模式 (2/5) - 静态变量、属性和方法及延迟绑定

    PHP高级程序设计 学习笔记 2014.06.10 Static(静态)关键字用来定义静态方法和属性,static 也可用于定义静态变量以及后期静态绑定. 1.静态变量 static variable ...

  7. Mac终端使用swift REPL异常处理方法

    Mac终端使用swift REPL异常处理方法 终端使用swift命令出现 warning: Swift error in module libmarisa.dylibDebug info from ...

  8. 速战速决 (5) - PHP: 动态地创建属性和方法, 对象的复制, 对象的比较, 加载指定的文件, 自动加载类文件, 命名空间

    [源码下载] 速战速决 (5) - PHP: 动态地创建属性和方法, 对象的复制, 对象的比较, 加载指定的文件, 自动加载类文件, 命名空间 作者:webabcd 介绍速战速决 之 PHP 动态地创 ...

  9. String类型的属性和方法

    × 目录 [1]属性 [2]对象通用方法 [3]访问字符方法[4]字符串拼接[5]创建子串方法[6]大小写转换[7]查找子串位置[8]正则匹配方法[9]去除首尾空格[10]字符串比较 前面的话 前面已 ...

随机推荐

  1. flush清空输入输出流

    #include <string.h> #include <stdio.h> #include <conio.h> #include <io.h> vo ...

  2. log4net 自定义Appender

    最近有个需求,使用log4net来记录日志,然后将数据保存到服务器端.一开始打算写一个windows service,定期上传日志. 后来又因为一些场景下不适应,因此直接改为保存内存中,到一定阀值之后 ...

  3. 10723 Cyborg Genes (LCS + 记忆化搜索)

    Problem F Cyborg Genes Time Limit 1 Second September 11, 2132. This is the day that marks the beginn ...

  4. django 实现上传文件功能

    需求:自己写一个文件上传功能 代码: urls.py from django.conf.urls import url from django.contrib import admin from ap ...

  5. 自动签到升级版(JS实现的每日定时任务)

    公司规定每日签到两次:日子太安逸了,有时候中午居然会忘记签到…… 于是,笔者寻思写一个自动签到的脚本:每天指定两个签到时段,每次打开页面,先检测当前是否为签到时段,如果在签到时段,则检查cookie中 ...

  6. ECharts学习总结(三):ECharts图表对象的初始化(init)详解以及注意事项

    一.相关js文件的引入 这里我们采用标签式引入文件的方式,我们引入两个js文件,一个是esl.js文件和一个echarts.js. <script src="js/esl.js&quo ...

  7. 深入理解java虚拟机笔记之一

    Java的技术体系主要有支撑java程序运行的虚拟机,提供各开发领域接口支持Java API,java编程语言及许多第三方java框架( 如Spring,Structs等)构成. 可以把Java程序设 ...

  8. TZOJ 1072: 编辑距离(动态规划)

    1072: 编辑距离 时间限制(普通/Java):1000MS/10000MS     内存限制:65536KByte 总提交: 917            測试通过:275 描写叙述 如果字符串的 ...

  9. Java中this与super

    l  对象的this引用 作用: this关键字就是让类中一个方法,访问该类中的另一个方法或属性. 1.构造器中引用该构造器正在初始化的对象. 2.在方法中引用调用该方法的对象(哪个对象调用的方法,t ...

  10. 浅谈PHP数据结构之栈

    今天開始进阶自己的PHP,首先一切的编程语言都须要修炼自己的"内功",何为程序猿的"内功",我想大概就是数据结构和算法了吧 .毕竟是灵魂,是普通程序猿到高级程序 ...