2015-04-14 14 views
271

Các mã sau biên dịch trong Swift 1.2:Các hàm/biến tĩnh so với lớp trong các lớp Swift?

class myClass { 
    static func myMethod1() { 
    } 
    class func myMethod2() { 
    } 
    static var myVar1 = "" 
} 

func doSomething() { 
    myClass.myMethod1() 
    myClass.myMethod2() 
    myClass.myVar1 = "abc" 
} 

sự khác biệt giữa một tĩnh chức năng và một lớp chức năng là gì? Tôi nên sử dụng cái nào và khi nào?

Nếu tôi cố gắng xác định một biến class var myVar2 = "", nó nói:

Lớp lưu trữ thuộc tính chưa được hỗ trợ trong lớp học; ý bạn là 'tĩnh'?

Khi tính năng này được hỗ trợ, điều gì sẽ là sự khác biệt được giữa một tĩnh biến và một lớp biến (ví dụ: khi cả hai được định nghĩa trong một lớp học)? Tôi nên sử dụng cái nào và khi nào?

(Xcode 6,3)

+0

câu hỏi tương tự ở đây: [tĩnh vs lớp như biến lớp/phương pháp (Swift)] (http://stackoverflow.com/questions/29206465/static-vs-class-as-class-variable-method-swift). –

Trả lời

434

staticclass cả kết hợp một phương pháp với một lớp học, chứ không phải là một thể hiện của một lớp. Sự khác biệt là các lớp con có thể ghi đè các phương thức class; họ không thể ghi đè lên các phương thức static.

class các thuộc tính về mặt lý thuyết sẽ hoạt động theo cùng một cách (các lớp con có thể ghi đè chúng), nhưng chúng không thể có trong Swift.

+48

Vậy sự khác biệt giữa hàm 'lớp cuối cùng' và hàm 'tĩnh' trong một lớp là gì? –

+28

@hippo_san, trong một lớp cơ sở, cả hai đều có chức năng giống nhau. Tuy nhiên, 'final' có thể được sử dụng để cắt bỏ các phần ghi đè khác khi được sử dụng trong một lớp con. Cả hai đều có vị trí của họ, tôi sẽ nói việc sử dụng 'static' hoặc' final' khi được sử dụng trên một hàm lớp là tầm thường và tùy thuộc vào lựa chọn kiểu của bạn. –

+7

ah, vì vậy 'static func foo() {}' trong Swift giống như 'public static final foo() {}' trong Java? – Supuhstar

20

Về OOP, câu trả lời là quá đơn giản:

Các lớp con có thể ghi đè lớp phương pháp, nhưng không thể ghi đè tĩnh phương pháp.

Ngoài bài viết của bạn, nếu bạn muốn khai báo một lớp biến (như bạn đã làm class var myVar2 = ""), bạn nên làm điều đó như sau:

class var myVar2:String { 
    return "whatever you want" 
} 
44

Tôi cố gắng trả lời và nhận xét về sân chơi mipadi của. Và nghĩ đến việc chia sẻ nó. Đây rồi. Tôi nghĩ câu trả lời của mipadi nên được đánh dấu là được chấp nhận.

class A{ 
    class func classFunction(){ 
    } 
    static func staticFunction(){ 
    } 
    class func classFunctionToBeMakeFinalInImmediateSubclass(){ 
    } 
} 

class B: A { 
    override class func classFunction(){ 

    } 

    //Compile Error. Class method overrides a 'final' class method 
    override static func staticFunction(){ 

    } 

    //Lets avoid the function called 'classFunctionToBeMakeFinalInImmediateSubclass' being overriden by subclasses 

    /* First way of doing it 
    override static func classFunctionToBeMakeFinalInImmediateSubclass(){ 
    } 
    */ 

    // Second way of doing the same 
    override final class func classFunctionToBeMakeFinalInImmediateSubclass(){ 
    } 

    //To use static or final class is choice of style. 
    //As mipadi suggests I would use. static at super class. and final class to cut off further overrides by a subclass 
} 

class C: B{ 
    //Compile Error. Class method overrides a 'final' class method 
    override static func classFunctionToBeMakeFinalInImmediateSubclass(){ 

    } 
} 
17

Tôi cũng nhận được sự nhầm lẫn này trong một dự án của tôi và thấy bài đăng này rất hữu ích. Cố gắng như vậy trong sân chơi của tôi và đây là bản tóm tắt. Hy vọng điều này sẽ giúp người có đặc tính lưu trữ và chức năng của loại static, final, class, trọng vars lớp vv

class Simple { 

    init() {print("init method called in base")} 

    class func one() {print("class - one()")} 

    class func two() {print("class - two()")} 

    static func staticOne() {print("staticOne()")} 

    static func staticTwo() {print("staticTwo()")} 

    final func yesFinal() {print("yesFinal()")} 

    static var myStaticVar = "static var in base" 

    //Class stored properties not yet supported in classes; did you mean 'static'? 
    class var myClassVar1 = "class var1" 

    //This works fine 
    class var myClassVar: String { 
     return "class var in base" 
    } 
} 

class SubSimple: Simple { 
    //Successful override 
    override class func one() { 
     print("subClass - one()") 
    } 
    //Successful override 
    override class func two() { 
     print("subClass - two()") 
    } 

    //Error: Class method overrides a 'final' class method 
    override static func staticOne() { 

    } 

    //error: Instance method overrides a 'final' instance method 
    override final func yesFinal() { 

    } 

    //Works fine 
    override class var myClassVar: String { 
     return "class var in subclass" 
    } 
} 

Và đây là các mẫu thử nghiệm:

print(Simple.one()) 
print(Simple.two()) 
print(Simple.staticOne()) 
print(Simple.staticTwo()) 
print(Simple.yesFinal(Simple())) 
print(SubSimple.one()) 
print(Simple.myStaticVar) 
print(Simple.myClassVar) 
print(SubSimple.myClassVar) 

//Output 
class - one() 
class - two() 
staticOne() 
staticTwo() 
init method called in base 
(Function) 
subClass - one() 
static var in base 
class var in base 
class var in subclass 
4

Có một sự khác biệt hơn. class có thể được sử dụng để xác định thuộc tính loại của loại tính toán chỉ. Nếu bạn cần một thuộc tính loại được lưu trữ được lưu trữ, hãy sử dụng static để thay thế.

"You define type properties with the static keyword. For computed type properties for class types, you can use the class keyword instead to allow subclasses to override the superclass’s implementation."

9

Kiểm tra trong Swift 4 cho thấy sự khác biệt về hiệu suất trong trình mô phỏng. Tôi đã tạo một lớp với "class func" và struct với "static func" và chạy chúng trong bài kiểm tra.

func tĩnh là:

  • 20% nhanh hơn mà không cần biên dịch tối ưu hóa
  • 38% nhanh hơn khi tối ưu hóa -whole-module-tối ưu hóa được kích hoạt.

Tuy nhiên, chạy cùng một mã trên iPhone 7 trong iOS 10.3 thể hiện chính xác cùng một hiệu suất.

Đây là dự án mẫu trong Swift 4 cho Xcode 9 nếu bạn muốn thử nghiệm bản thân https://github.com/protyagov/StructVsClassPerformance

2

Cả từ khóa staticclass cho phép chúng tôi để đính kèm các biến để một lớp học chứ không phải là trường hợp của một lớp. Ví dụ: bạn có thể tạo lớp Student với các thuộc tính như nameage, sau đó tạo thuộc tính tĩnh thuộc sở hữu của chính lớp Student thay vì các cá thể riêng lẻ.

đâu staticclass khác nhau là cách họ hỗ trợ kế thừa: Khi bạn thực hiện một thuộc tính tĩnh nó trở nên thuộc sở hữu của lớp và không thể thay đổi bởi các lớp con, trong khi đó khi bạn sử dụng lớp nó có thể được ghi đè nếu cần thiết.

Ví dụ, đây là một lớp Person với một static bất động sản và một tài sản lớp:

class Person { 
    static var count: Int { 
     return 250 
    } 

    class var averageAge: Double { 
     return 30 
    } 
} 

Nếu chúng ta tạo ra một class Student bởi kế thừa từ Person, cố gắng để ghi đè count (tài sản tĩnh) sẽ thất bại trong việc biên dịch, trong khi cố gắng để ghi đè averageAge (thuộc tính class) là OK:

class Student: Person { 
    // THIS ISN'T ALLOWED 
    override static var count: Int { 
     return 150 
    } 

    // THIS IS ALLOWED 
    override class var averageAge: Double { 
     return 19.5 
    } 
} 
Các vấn đề liên quan