一:访问权限变更(原文链接:http://www.jianshu.com/p/604305a61e57)
新的访问控制fileprivate和open
在swift 3中新增加了两种访问控制权限 fileprivate 和 open 。下面将对这两种新增访问控制做详细介绍。
fileprivate
在原有的swift中的 private 其实并不是真正的私有,如果一个变量定义为private,在同一个文件中的其他类依然是可以访问到的。这个场景在使用extension的时候很明显。
class User {
private var name = "private"
}
extension User{
var accessPrivate: String {
return name
}
}
这样带来了两个问题:
- 当我们标记为private时,意为真的私有还是文件内可共享呢?
- 当我们如果意图为真正的私有时,必须保证这个类或者结构体在一个单独的文件里。否则可能同文件里其他的代码访问到。
由此,在swift 3中,新增加了一个 fileprivate 来显式的表明,这个元素的访问权限为文件内私有。过去的private对应现在的fileprivate。现在的private则是真正的私有,离开了这个类或者结构体的作用域外面就无法访问。
open
open则是弥补public语义上的不足。 现在的pubic有两层含义:
- 这个元素可以在其他作用域被访问
- 这个元素可以在其他作用域被继承或者override
继承是一件危险的事情。尤其对于一个framework或者module的设计者而言。在自身的module内,类或者属性对于作者而言是清晰的,能否被继承或者override都是可控的。但是对于使用它的人,作者有时会希望传达出这个类或者属性不应该被继承或者修改。这个对应的就是 final 。
final 的问题在于在标记之后,在任何地方都不能override。而对于lib的设计者而言,希望得到的是在module内可以被override,在被import到其他地方后其他用户使用的时候不能被override。
这就是 open 产生的初衷。通过open和public标记区别一个元素在其他module中是只能被访问还是可以被override。
下面是例子:
public class NonSubclassableParentClass {
public func foo() {}
open func bar() {}
public final func baz() {}
}
open class SubclassableParentClass {
public var size : Int
public func foo() {}
open func bar() {}
public final func baz() {}
}
public final class FinalClass { }
import ModuleA
class SubclassA : NonSubclassableParentClass { }
class SubclassB : SubclassableParentClass {
override func foo() { }
override func bar() { }
}
open class SubclassC : SubclassableParentClass {
override func bar() { }
}
open class SubclassD : SubclassableParentClass {
open override func bar() { }
}
open class SubclassE : SubclassableParentClass {
public final override func bar() { }
}
现在的访问权限则依次为:open,public,internal,fileprivate,private。
有的人会觉得访问权限选择的增加加大了语言的复杂度。但是如果我们思考swift语言的设计目标之一就是一门安全的语言(“Designed for Safety”)就能理解这次的改动。更加明确清晰的访问权限控制可以使程序员表达出更准确的意图,当然也迫使在编码时思考的更加深入
二:方法返回值
Swift 3.0 中方法的返回值必须有接收否则会报警告,当然其实主要目的是为了避免开发人员忘记接收返回值的情况,但是有些情况下确实不需要使用返回值可以使用"_"接收来忽略返回值。当然你也可以增加@discardableResult 声明,告诉编译器此方法可以不用接收返回值。
struct Caculator {
func sum(a:Int,b:Int) -> Int {
return a + b
}
@discardableResult
func func1(a:Int,b:Int) ->Int {
return a - b + 1
}
}
let ca = Caculator()
ca.sum(a: 1,b: 2)
let _ = ca.sum(a: 1,b: 2)
ca.func1(a: 1,b: 2)
三:函数或方法参数
在Swift的历史版本中出现过在调用函数时不需要指定任何函数参数(或者从第二个参数开始指定参数名),在调用方法时则必须从第二个参数开始必须指定参数名等多种情况,而在Swift3.0中不管是函数还是方法都必须从第一个参数开始必须指定参数名(当然可以使用“_”明确指出调用时省略参数)。
func sum(num1:Int,num2:Int)->Int{
return num1 + num2
}
sum(num1: 1,num2: 2)
func increase(a:Int){
var a = a
a += 1
}
func increase( a:inout Int) {
a += 1
}
四:方法返回值
Swift 3.0 中方法的返回值必须有接收否则会报警告,当然其实主要目的是为了避免开发人员忘记接收返回值的情况,但是有些情况下确实不需要使用返回值可以使用"_"接收来忽略返回值。当然你也可以增加@discardableResult 声明,告诉编译器此方法可以不用接收返回值。
struct Caculator {
func sum(a:Int,b: 2)
五:可选类型
Swift3.0对于可选类型控制更加严谨,隐式可选类型和其他类型的运算之后获得的是可选类型而不是隐式可选类型。
let a:Int! = 1
let b = a + 1
let c = a
六:Selector的变化
Selector的改变其实从1.0到3.0经历了多次变化,从最早的@Selector("method:") 到现在的#selector(method(param1:)) 可以说经历了多次修改,好在它变得越来越好,毕竟字符串操作对于语法检查来说是很无助的。
class MyClass {
@objc func sum(a:Int,b:Int) -> Int {
return a + b
}
func func1(){
let _ = #selector(sum(a:b:))
}
}
七:协议中的可选方法
在Swift3.0之前如果要定义协议中可选方法,只需要给协议加上@objc之后方法使用optional修饰就可以了,但是Swift3.0中除了协议需要@objc修饰,可选方法也必须使用@objc来修饰。
@objc protocol MyProtocol {
@objc optional func func1()
func func2()
}
八:取消++、--操作符
var d = 1
d++
九:取消C风格for循环
for i in 0 ..< 10 {
debugPrint(i)
}
十:命名
let url1 = URL(string: "www.cmjstudio.com")
let isFileURL = url1?.isFileURL
let data1 = Data()
var array1 = [1,2,3]
array1.append(contentsOf: [4,5,6])
array1.remove(at: 0)
let color1 = UIColor.red()
let label1 = UILabel()
label1.textAlignment = .center
let btn1 = UIButton()
btn1.setTitle("hello",for: UIControlState())
十一:去C风格
Swift发展初期很多类库的引入依然保持的ObjC风格,但是ObjC由于根出C语言,因此很多操作其实并不是对象和方法操作而是C语言的函数形式。到了Swift3.0之后这一现状将发生变化,全局函数将会变成某些类型的方法;某些常量定义将以某个枚举类型的成员来表示。
let rect1 = CGRect(x: 0,y: 0,width: 100,height: 100)
if let context1 = UIGraphicsGetCurrentContext() {
CGContext.fillPath(context1)
}
let queue = DispatchQueue(label: "myqueue")
queue.async {
debugPrint("hello world!")
}
NotificationCenter.defaultCenter().addObserver(self,selector: #selector(userDefaultChange()),name: UserDefaults.didChangeNotification,object: nil)
集合API的变化
let array1 = [1,3]
let next = array1.index(after: 0)
let first = array1.first { (element) -> Bool in
element > 1
}
let r = Range(0..<3)
for subview in sequence(first: self.view,next: { $0?.superview }){
debugPrint(subview)
}
十二:新的浮点协议
Float、Double、CGFloat使用了新的协议,提供了提供 IEEE-754标准的属性和方法。
let a = 2 * Float.pi
let b = 2.0 * .pi
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|