2016-08-18 63 views

回答

212

fileprivate現在是什麼private曾經在以前 迅速發佈:從 訪問同一個源文件。標註爲private的聲明現在只能在聲明的詞法範圍內訪問。 因此privatefileprivate更具限制性。

Swift 4,如果在同一個源文件中定義了擴展名,類型內的私有聲明可以被相同類型的擴展訪問。

實施例(全部在一個源文件):

class A { 
    private func foo() {} 
    fileprivate func bar() {} 

    func baz() { 
     foo() 
     bar() 
    } 
} 

extension A { 
    func test() { 
     foo() // Swift 3: error: use of unresolved identifier 'foo' 
       // Swift 4: no error because extension is in same source file 
     bar() 
    } 
} 

let a = A() 
a.foo() // error: 'foo' is inaccessible due to 'private' protection level 
a.bar() 
  • 私人foo方法僅 的class A { ... }定義的範圍內是可訪問的。它甚至不能從 擴展到該類型(在Swift 3中,請參閱下面的第二個註釋,以瞭解Swift 4中 的變化)。

  • 文件私人bar方法可從同一個源文件訪問。

注:

  1. SE-0159 – Fix Private Access Levels建議恢復到斯威夫特4雨燕2個語義迅速進化郵件列表上一個漫長而有爭議的討論後建議,提案rejected

  2. 提案SE-0169 – Improve Interaction Between private Declarations and Extensions建議,使同類型的 擴展訪問的類型的內部private 聲明如果擴展在相同的源文件中定義。 這個建議被採納和實施斯威夫特4

+2

如果您將代碼從Swift 2自動轉換爲3,則Xcode會將'private'變成'fileprivate'。但是,如果你有奢侈的手工操作,你可以通過'private'作爲'private'來獲益,如果它編譯的話,一切都很好。 –

1
class Privacy { 

    fileprivate(set) var pu:Int { 
     get { 
      return self.pr 
     } 
     set { 
      self.pr = newValue 
     } 
    } 
    private var pr:Int = 0 
    fileprivate var fp:Int = 0 


    func ex() { 
     print("\(self.pu) == \(self.pr) and not \(self.fp)") 
    } 
} 


extension Privacy { 

    func ex2() { 
     self.pu = 5 
     self.ex() 
    } 

} 

我喜歡這個,因爲它是高德超級簡單。

嘗試改變fileprivate私人(反之亦然),看看在編譯會發生什麼......

4

根據經驗,實際的規則是,你使用私有變量,常量,即僅用於內部結構和類在你的類/結構的聲明中。你可以在你的擴展中使用fileprivate,在你的類/結構所在的同一文件中使用,但不在它們定義的大括號(即它們的詞法範圍)之外。

class ViewController: UIViewController { 
     @IBOutlet var tableView: UITableView! 
     //This is not used outside of class Viewcontroller 
     private var titleText = "Demo" 
     //This gets used in the extension 
     fileprivate var list = [String]() 
     override func viewDidLoad() { 
      navigationItem.title = titleText 
     } 
    } 

    extension ViewController: UITableViewDataSource { 
     func numberOfSections(in tableView: UITableView) -> Int { 
      return list.count 
     } 
    } 
56

我只是畫一個關於私人,fileprivate,打開的圖表,密切

希望它可以迅速幫助您,爲文字說明請參見馬丁 - [R的回答

感謝您的蘇丹的答案。此圖只適用於在同一模塊

enter image description here

+6

注意,'fileprivate'沒有鏈接到擴展名,而是鏈接到文件(在另一個文件中寫入A類的擴展名將不允許使用'fileprivate'成員) – Vince

+1

並且thx @Vince糾正了我的錯誤。 :) –

+1

這看起來不正確。你錯過了關鍵點。您必須區分同一模塊內和不同模塊中的類。如果它們在不同的模塊中,那麼'public'將不允許你繼承,因此第三個圖像是不正確的。另外,如果你能看到它,你總是可以給任何課程添加一個擴展。然後解釋擴展的可視性並不是一個好主意。 – Sulthan

3

在下面的例子上,通過privatefileprivate修改語言結構似乎表現相同:

fileprivate func fact(_ n: Int) -> Int { 
    if (n == 0) { 
     return 1 
    } else { 
     return n * fact(n - 1) 
    } 
} 

private func gauss(_ n: Int) -> Int { 
    if (n == 0) { 
     return 0 
    } else { 
     return n + gauss(n - 1) 
    } 
} 

print(fact(0)) 
print(fact(5)) 
print(fact(3)) 

print(gauss(10)) 
print(gauss(9)) 

這是根據直覺,我猜。但是,有沒有例外?

最好的問候。

3

雖然@ MartinR's和@ StephenChen的回答都很完美,Swift 4改變了一些事情。

私人現在被認爲是私有的它宣佈它的類和它的擴展。

FilePrivate在該文件中被認爲是私有的,無論是定義該變量的類,擴展名還是定義在該文件中的任何其他類。

0

在Swift 4.0中,Private現在可以在擴展中訪問,但在同一個文件中。如果你聲明/定義在其他文件擴展名,那麼你的私有變量不會對您的擴展訪問**

文件私人
文件,私接限制使用的實體自身的定義源文件。當在整個文件中使用這些詳細信息時,使用文件私有訪問來隱藏特定功能塊的實現細節。
語法:fileprivate <var type> <variable name>
實施例:fileprivate class SomeFilePrivateClass {}


私人
私人接入限制使用的實體到封閉聲明的,並且是在相同的該聲明的擴展文件。當這些細節僅在單個聲明中使用時,使用私有訪問來隱藏特定功能的實現細節。
語法:private <var type> <variable name>
例子:private class SomePrivateClass {}


這是所有訪問級別的更多細節:Swift - Access Levels

看看這個圖片:
文件: ViewController.swift
這裏的擴展和視圖控制器都是相同的文件,因此私有變量testPrivateAccessLevel是擴展訪問

enter image description here


文件: TestFile.swift
這裏延伸和視圖控制器都是在不同的文件,因此私有變量testPrivateAccessLevel是不是在擴展訪問。

enter image description here

enter image description here


下面類ViewController2ViewController一個子類,都是在同一個文件中。這裏私有變量testPrivateAccessLevel不能在Subclass中訪問,但fileprivate可以在子類中訪問。

enter image description here

0

filePrivate - 訪問控制研究水平是在文件中。

情況1:如果我們創建的擴展,在同一類文件,並嘗試訪問fileprivate功能或fileprivate財產及其延伸 - 允許訪問
情況下2:如果我們創建新的文件擴展類的 - 現在嘗試訪問fileprivate功能或fileprivate財產 - 不允許訪問

私人 - 訪問控制水平與詞彙範圍

情況1:如果屬性或函數在類中聲明爲私有 - 那麼範圍默認爲類。 案例2:如果私有實例是在函數體中聲明的 - 那麼實例的作用域限於函數體。

相關問題