结构体中,除了init 函数外,其他函数中如果有修改自身属性,必须声明为 mutating
struct s {
var str : String = ""
mutating func(s1 : String) {
self.str = s1
}
}
类方法和static方法都是通过 类名(结构名) 直接调用的方法。 但 类方法可以被子类重写,而static 不行.
class EqualClass {
class func canOverride() {
print("EqualClass canOverride")
}
static func cannotOverride() {
print("EqualClass cannotOverride")
}
}
class SubEqualClass : EqualClass {
override class func canOverride() {
print("SubEqualClass canOverride")
}
//下面代码无法编译
override static func cannotOverride() {
print("SubEqualClass cannotOverride")
}
}
在类,结构或是枚举 声明中,可以定义下标脚本,通过一个或多个索引来访问实例里的数据。
class EqualClass {
subscript(first : Int, second : String) -> String {
return "Int=\(first) second=\(second)"
}
}
let object = EqualClass()
print("subscript = "+object[1,"bb"]) //用两个索引参数来访问上面声明的下标脚本
类和结构体在实例创建时,必须为所有存储型属性设置合适的初始值。可选类型的不用。 存储属性在构造器中赋值时,它们的值是被直接设置的,不会触发任何属性观测器(也就是didSet,willSet等)。case 1 同时,属性在声明处的初始化也是不会触发属性观测器的。 Case 2
class SubCls {
override init(v : String) {
self.sss = v + "sss" //case 1
}
var sss : String? = "" { //case 2
willSet {
print("\(newValue)")
}
}
}

在某些自定义条件不满足时,在 可失败构造器内返回nil,表示构造失败. 你可以用一个非可失败构造器覆盖一个可失败构造器,但反过来却行不通。 一个非可失败的构造器永远也不能代理调用一个可失败构造器。
Class Failure {
init?(v : Int) {
if v < 0 { return nil }
}
init(v1 : Int) {
}
}
class SubFailure : Failure {
override init?(v : Int) {
super.init(v1: v) //可失败构造器 可以调用父类的 非可失败构造器
}
init(v2 : Int) { //编译错误! 非可失败构造器不能调用父类的 可失败构造器
super.init(v: v2)
}
}
用 associatedtype 关键字来设置关联类型实例。 声明的关联类型可以替代任何其他类型,类似泛型。
protocol Cont {
associatedtype ItemType // 该协议声明关联类型,可以替代任何其他类型
mutating func append(_ item: ItemType)
}
extension Int : Cont {
func append(_ item: Int) { //关联类型 Int
print("Int append")
}
}
extension Double : Cont {
func append(_ item: Double) { //关联类型Double
print("Double append")
}
}
类型约束语句可以确保 指定的类型符合 泛型或是类的定义。 可以在参数列表中定义泛型参数的约束,以保证参数类型符合你的预期。 Where 放在函数的所有参数类型最后,可以接多个约束语句,来满足自己对参数类型的需求。
样例代码(自定义一个Stack容器类,实现一个compareStack函数,对比两个容器里元素是否完全一致):
//先声明协议,声明一下 compareStack 里用到的容器类的方法
protocol Cont {
associatedtype ItemType
var count : Int {get}
// 添加一个新元素到容器里
mutating func append(_ item: ItemType)
subscript(i : Int) -> ItemType {get}
}
//实现自定义Stack 容器类
class MyStack<Element> : Cont {
var myItems : [Element] = []
init(v : Element...) {
for value in v {
myItems.append(value)
}
}
var count: Int {
get {myItems.count}
}
func append(_ item: Element) {
myItems.append(item)
}
subscript(i : Int) -> Element {
return myItems[i]
}
}
// 扩展,将 Array 当作 Cont 来使用, 因为Array本身也实现了 Cont里声明的方法
extension Array: Cont {}
//容器对比函数
func compareStack<C1 : Cont, C2 : Cont>(stack1 : C1, stack2 : C2) -> Bool //C1 和 C2 类型都必须实现Cont 协议
where C1.ItemType == C2.ItemType, //约束1,C1的Element和C2的必须相同
C1.ItemType : Equatable { //约束2,C1的Element 必须实现Equatable 协议
guard stack1.count == stack2.count else {
return false
}
for i in 0..<stack2.count {
if stack1[i] != stack2[i] { return false }
}
return true
}
let arrr1 = [1,2,3] //一个Array
let stack1 = MyStack.init(v: 1,2,3) //一个MyStack容器
if compareStack(stack1: arrr1, stack2: stack1) { //对比Array和MyStack容器元素是否完全一致
print("the same!") //会进入这里
}