स्विफ्ट में स्टेटिक फंक और क्लास फंक के बीच अंतर क्या है?


334

मैं स्विफ्ट लाइब्रेरी में ये परिभाषा देख सकता हूं:

extension Bool : BooleanLiteralConvertible {
    static func convertFromBooleanLiteral(value: Bool) -> Bool
}

protocol BooleanLiteralConvertible {
    typealias BooleanLiteralType
    class func convertFromBooleanLiteral(value: BooleanLiteralType) -> Self
}

के रूप में परिभाषित एक सदस्य समारोह static funcऔर एक के रूप में परिभाषित एक और के बीच अंतर क्या है class func? क्या यह सिर्फ़ staticसंरचनाओं और एनमों के स्थिर कार्यों और classवर्गों और प्रोटोकॉलों के लिए है? क्या कोई अन्य मतभेद हैं जिनके बारे में किसी को पता होना चाहिए? वाक्य रचना में ही यह अंतर होने का औचित्य क्या है?


3
वास्तव में कोई अंतर नहीं है। वे मेरे द्वारा बताए गए ढांचे में क्लास फंक का इस्तेमाल नहीं कर सकते थे, इसलिए स्टैटिक फंक। स्ट्रक्चर फंक एक अच्छा उम्मीदवार होता। यदि आप मुझसे पूछें तो यह थोड़ा कठिन है, लेकिन वे शब्द हैं।
फेब्रीस ट्रुइलोट डी चैंबर 9

2
बोनस प्रश्न, फिर: क्या एक प्रोटोकॉल एक प्रोटोकॉल के अनुरूप हो सकता है class func? हमारे पास अभी जो जानकारी है, उसके साथ यह अंतर बेकार लगता है, है ना?
जीन-फिलिप पेलेट

3
हाँ तुम कर सकते हो। अजीब बात है ना?
फेब्रिस ट्रिल्लॉट डी चैंबर 9

7
भारी अंतर आप ओवरराइड कर सकते हैं class funcरों
fattie

1
विचार करने के लिए:error: class methods are only allowed within classes; use 'static' to declare a static method
गेब्रियल गोंक्लेव्स

जवाबों:


238

क्या यह केवल इतना है कि स्थिरिकारी संरचना और एनम के स्थिर कार्यों के लिए है, और वर्ग और प्रोटोकॉल के लिए वर्ग है?

यही मुख्य अंतर है। कुछ अन्य अंतर यह है कि क्लास फ़ंक्शंस गतिशील रूप से भेजे जाते हैं और उपवर्गों द्वारा ओवरराइड किए जा सकते हैं।

प्रोटोकॉल क्लास कीवर्ड का उपयोग करते हैं, लेकिन यह प्रोटोकॉल को लागू करने से संरचना को बाहर नहीं करता है, वे सिर्फ स्थैतिक का उपयोग करते हैं। क्लास को प्रोटोकॉल के लिए चुना गया था ताकि स्टेटिक या क्लास का प्रतिनिधित्व करने के लिए तीसरा कीवर्ड न हो।

इस विषय पर क्रिस लैटनर से:

हमने सिंटैक्स को एकजुट करने पर विचार किया (उदाहरण के लिए "टाइप" कीवर्ड के रूप में), लेकिन यह वास्तव में केवल चीजें नहीं हैं। कीवर्ड "क्लास" और "स्टैटिक" परिचित के लिए अच्छे हैं और काफी वर्णनात्मक हैं (एक बार जब आप समझते हैं कि + तरीके कैसे काम करते हैं), और कक्षाओं के लिए संभावित रूप से स्थिर तरीकों को जोड़ने के लिए दरवाजा खोलें। इस मॉडल की प्राथमिक विचित्रता यह है कि प्रोटोकॉल को एक कीवर्ड चुनना होता है (और हमने "क्लास" चुना है), लेकिन संतुलन पर यह सही ट्रेडऑफ़ है।

और यहाँ एक स्निपेट है जो वर्ग कार्यों के ओवरराइड व्यवहार से कुछ दिखाता है:

class MyClass {
    class func myFunc() {
        println("myClass")
    }
}

class MyOtherClass: MyClass {
    override class func myFunc() {
        println("myOtherClass")
    }
}

var x: MyClass = MyOtherClass()
x.dynamicType.myFunc() //myOtherClass
x = MyClass()
x.dynamicType.myFunc() //myClass

4
अहा, बहुत महत्वपूर्ण बिंदु यह है कि क्लास फ़ंक्शंस गतिशील रूप से भेजे जाते हैं! लेकिन क्या आप ऐसा कोई उदाहरण दे सकते हैं? आपको कक्षा का नाम कहीं लिखना होगा, है ना? तो क्यों न वैधानिक रूप से उस वर्ग के कार्यान्वयन को चुना जाए?
जीन-फिलिप पेलेट

1
एक और पूरक प्रश्न: आपको बोली कहाँ से मिली?
जीन-फिलिप पेलेट

मेरी समझ यह है कि क्लास फ़ंक्शंस बहुत ज्यादा काम करते हैं जैसे कि हुड के नीचे objc + तरीके
Connor

1
क्या मैं यहां एक सरल उत्तर लिंक प्रदान कर सकता हूं? stackoverflow.com/questions/29636633/…
एलनिनली

1
@ Jean-PhilippePellet उपरोक्त उदाहरण में ... यदि आप के static func myFunc()बजाय आप का उपयोग करते हैं तो आपको class func myFuncनिम्न त्रुटि मिलेगी: स्थैतिक विधि को ओवरराइड नहीं कर सकते । क्यों? क्योंकि यह ऐसा है जैसे कि इसके साथ चिह्नित किया गया है final। अधिक जानकारी के लिए। नीचे देखें NextD का जवाब इसके साथ x.dynamicTypeही अब इसे बदल दिया गया हैtype(of:x)
Honey

246

स्पष्ट होने के लिए, मैं यहां एक उदाहरण देता हूं,

class ClassA {
  class func func1() -> String {
    return "func1"
  }

  static func func2() -> String {
    return "func2"
  }

  /* same as above
  final class func func2() -> String {
    return "func2"
  }
  */
}

static func वैसा ही है final class func

क्योंकि यह है final, हम इसे नीचे के रूप में उपवर्ग में ओवरराइड नहीं कर सकते हैं:

class ClassB : ClassA {
  override class func func1() -> String {
    return "func1 in ClassB"
  }

  // ERROR: Class method overrides a 'final` class method
  override static func func2() -> String {
    return "func2 in ClassB"
  }
}

18
आप शैंपू, महान जवाब .. मैं इस अंतर की तलाश कर रहा था .. जेक !!
अभिमन्यु राठौर

5
उत्तम। प्रभावशाली।
मेहुल

5
इसे सही उत्तर के रूप में चिह्नित किया जाना चाहिए। साफ़ सुथरा!
अभिनववीर 23

1
सबसे अच्छा स्पष्टीकरण! यह मुझे एक और संदेह की ओर ले गया। क्या 'क्लास फंक' का उपयोग करने का कोई स्पष्ट कारण है? मेरा मतलब है कि यदि आप 'फंक' का उपयोग करते हैं तो इसे भी उसी तरह से ओवरराइड किया जा सकता है, तो क्या अंतर है?
मार्कोस रेबुकास

1
@MarcosReboucas यदि मैं आपके प्रश्न को सही ढंग से समझता हूं, class funcतो सामान्य से अलग है , funcहालांकि दोनों को ओवरराइड किया जा सकता है। लेकिन funcएक उदाहरण / वस्तु के लिए है और class funcइसे कक्षा के माध्यम से एक्सेस किया जा सकता है जैसेClassA.classFunc()
जेक लिन

78

मैंने खेल के मैदान में कुछ प्रयोग किए और कुछ निष्कर्ष निकाले।

टी एल; डॉ यहां छवि विवरण दर्ज करें

जैसा कि आप देख सकते हैं, के मामले classमें class funcया का उपयोगstatic func आदत के सिर्फ एक सवाल है।

स्पष्टीकरण के साथ खेल का मैदान उदाहरण:

class Dog {
    final func identity() -> String {
        return "Once a woofer, forever a woofer!"
    }

    class func talk() -> String {
        return "Woof woof!"
    }

    static func eat() -> String {
        return "Miam miam"
    }

    func sleep() -> String {
        return "Zzz"
    }
}

class Bulldog: Dog {
    // Can not override a final function
//    override final func identity() -> String {
//        return "I'm once a dog but now I'm a cat"
//    }

    // Can not override a "class func", but redeclare is ok
    func talk() -> String {
        return "I'm a bulldog, and I don't woof."
    }

    // Same as "class func"
    func eat() -> String {
        return "I'm a bulldog, and I don't eat."
    }

    // Normal function can be overridden
    override func sleep() -> String {
        return "I'm a bulldog, and I don't sleep."
    }
}

let dog = Dog()
let bullDog = Bulldog()

// FINAL FUNC
//print(Dog.identity()) // compile error
print(dog.identity()) // print "Once a woofer, forever a woofer!"
//print(Bulldog.identity()) // compile error
print(bullDog.identity()) // print "Once a woofer, forever a woofer!"

// => "final func" is just a "normal" one but prevented to be overridden nor redeclared by subclasses.


// CLASS FUNC
print(Dog.talk()) // print "Woof woof!", called directly from class
//print(dog.talk()) // compile error cause "class func" is meant to be called directly from class, not an instance.
print(Bulldog.talk()) // print "Woof woof!" cause it's called from Bulldog class, not bullDog instance.
print(bullDog.talk()) // print "I'm a bulldog, and I don't woof." cause talk() is redeclared and it's called from bullDig instance

// => "class func" is like a "static" one, must be called directly from class or subclassed, can be redeclared but NOT meant to be overridden.

// STATIC FUNC
print(Dog.eat()) // print "Miam miam"
//print(dog.eat()) // compile error cause "static func" is type method
print(Bulldog.eat()) // print "Miam miam"
print(bullDog.eat()) // print "I'm a bulldog, and I don't eat."

// NORMAL FUNC
//print(Dog.sleep()) // compile error
print(dog.sleep()) // print "Zzz"
//print(Bulldog.sleep()) // compile error
print(bullDog.sleep()) // print "I'm a bulldog, and I don't sleep."

7
आपके उदाहरण किसी अन्य उत्तर में मुख्य अंतर के रूप में उल्लिखित मामले को कवर नहीं करते हैं: classकार्यों का गतिशील प्रेषण बनाम staticलोगों का स्थिर बंधन ।
जीन-फिलिप पेलेट

1
समझ कार्यों के लिए महान व्याख्या।
युकेल बेयराम

33
class funcअतिश्योक्ति नहीं है ?
इलियान ओनोफ्रेई

9
यदि आप एक स्थिर विधि को ओवरराइड करने का प्रयास करते हैं, तो आप एक त्रुटि प्राप्त करेंगे। हालाँकि आप एक वर्ग विधि को ओवरराइड कर सकते हैं। स्वीकृत उत्तर देखें
हनी

8
class funcअतिश्योक्तिपूर्ण है। मैं इसे अन्यथा वोट देता; अनुसंधान और उदाहरण प्यार!
बेन लेगियरियो

52

एक प्रकार की परिवर्तनीय संपत्ति घोषित करने के लिए, staticघोषणा संशोधन के साथ घोषणा को चिह्नित करें । वर्ग classउपवर्गों को सुपरक्लास के कार्यान्वयन को ओवरराइड करने की अनुमति देने के बजाय घोषित संशोधक के साथ टाइप किए गए गुणों को चिह्नित कर सकते हैं । टाइप प्रॉपर्टीज में टाइप प्रॉपर्टीज की चर्चा होती है।

नोट
एक कक्षा की घोषणा में, कीवर्ड staticका एक ही प्रभाव होता है कि घोषणा classऔर finalघोषणा दोनों संशोधक के साथ अंकन ।

स्रोत: द स्विफ्ट प्रोग्रामिंग लैंग्वेज - टाइप वेरिएबल प्रॉपर्टीज


5
सवाल 'स्टैटिक फंक' और 'क्लास फंक' के बारे में पूछ रहा है। यह प्रकार के गुणों के बारे में नहीं पूछ रहा है। तो यह सवाल का जवाब नहीं देता है - हालांकि गुणों के संबंध में इन खोजशब्दों के संदर्भ को समझना महत्वपूर्ण है।
एतेलुज़

यह उत्तर केवल गलत प्रश्न पर है, शायद यह गलती से यहां पोस्ट किया गया था?
फटी

15

सेब द्वारा प्रकाशित स्विफ्ट 2.2 पुस्तक के अनुसार:

“आप staticविधि के फंक कीवर्ड से पहले कीवर्ड लिखकर विधियों का संकेत देते हैं । उप-वर्ग को अनुमति देने के लिए कक्षाएँ भी classकीवर्ड का उपयोग कर सकती हैं ताकि उस पद्धति के सुपरक्लास के कार्यान्वयन को ओवरराइड किया जा सके । "


10

Swift2.0 से, Apple कहता है:

"जब आप किसी प्रोटोकॉल में परिभाषित करते हैं, तो हमेशा स्थैतिक कीवर्ड के साथ संपत्ति प्रकार की उपसर्ग आवश्यकताएं होती हैं। यह नियम तब भी संबंधित होता है, जब किसी वर्ग द्वारा लागू की गई प्रॉपर्टी की आवश्यकताओं को वर्ग या स्थिर कीवर्ड के साथ उपसर्ग किया जा सकता है:"


5

यह उदाहरण हर पहलू को स्पष्ट करेगा!

import UIKit

class Parent {
    final func finalFunc() -> String { // Final Function, cannot be redeclared.
        return "Parent Final Function."
    }

    static func staticFunc() -> String { // Static Function, can be redeclared.
        return "Parent Static Function."
    }

    func staticFunc() -> String { // Above function redeclared as Normal function.
        return "Parent Static Function, redeclared with same name but as non-static(normal) function."
    }

    class func classFunc() -> String { // Class Function, can be redeclared.
        return "Parent Class Function."
    }

    func classFunc() -> String { // Above function redeclared as Normal function.
        return "Parent Class Function, redeclared with same name but as non-class(normal) function."
    }

    func normalFunc() -> String { // Normal function, obviously cannot be redeclared.
        return "Parent Normal Function."
    }
}

class Child:Parent {

    // Final functions cannot be overridden.

    override func staticFunc() -> String { // This override form is of the redeclared version i.e: "func staticFunc()" so just like any other function of normal type, it can be overridden.
        return "Child Static Function redeclared and overridden, can simply be called Child Normal Function."
    }

    override class func classFunc() -> String { // Class function, can be overidden.
        return "Child Class Function."
    }

    override func classFunc() -> String { // This override form is of the redeclared version i.e: "func classFunc()" so just like any other function of normal type, it can be overridden.
        return "Child Class Function, redeclared and overridden, can simply be called Child Normal Function."
    }

    override func normalFunc() -> String { // Normal function, can be overridden.
        return "Child Normal Function."
    }
}

let parent = Parent()
let child = Child()

// Final
print("1. " + parent.finalFunc())   // 1. Can be called by object.
print("2. " + child.finalFunc())    // 2. Can be called by object, parent(final) function will be called.
// Parent.finalFunc()               // Cannot be called by class name directly.
// Child.finalFunc()                // Cannot be called by class name directly.

// Static
print("3. " + parent.staticFunc())  // 3. Cannot be called by object, this is redeclared version (i.e: a normal function).
print("4. " + child.staticFunc())   // 4. Cannot be called by object, this is override form redeclared version (normal function).
print("5. " + Parent.staticFunc())  // 5. Can be called by class name directly.
print("6. " + Child.staticFunc())   // 6. Can be called by class name direcly, parent(static) function will be called.

// Class
print("7. " + parent.classFunc())   // 7. Cannot be called by object, this is redeclared version (i.e: a normal function).
print("8. " + child.classFunc())    // 8. Cannot be called by object, this is override form redeclared version (normal function).
print("9. " + Parent.classFunc())   // 9. Can be called by class name directly.
print("10. " + Child.classFunc())   // 10. Can be called by class name direcly, child(class) function will be called.

// Normal
print("11. " + parent.normalFunc())  // 11. Can be called by object.
print("12. " + child.normalFunc())   // 12. Can be called by object, child(normal) function will be called.
// Parent.normalFunc()               // Cannot be called by class name directly.
// Child.normalFunc()                // Cannot be called by class name directly.

/*
 Notes:
 ___________________________________________________________________________
 |Types------Redeclare------Override------Call by object------Call by Class|
 |Final----------0--------------0---------------1------------------0-------|
 |Static---------1--------------0---------------0------------------1-------|
 |Class----------1--------------1---------------0------------------1-------|
 |Normal---------0--------------1---------------1------------------0-------|
 ---------------------------------------------------------------------------

 Final vs Normal function: Both are same but normal methods can be overridden.
 Static vs Class function: Both are same but class methods can be overridden.
 */

आउटपुट: सभी प्रकार के फ़ंक्शन का आउटपुट


-6

इसे प्रकार विधियाँ कहा जाता है, और उदाहरण वाक्य विधियों की तरह, डॉट सिंटैक्स के साथ कहा जाता है। हालाँकि, आप उस प्रकार के प्रकार को कॉल करते हैं, उस प्रकार के इंस्टेंस पर नहीं। यहां बताया गया है कि आप SomeClass नामक वर्ग पर एक प्रकार की विधि कैसे कहते हैं:


1
class SomeClass {क्लास func someTypeMethod () {// टाइप मेथड इम्प्लीमेंटेशन इधर}}} SomeClass.someTypeMethod ()
कुमार उत्सव

इस सवाल का जवाब बिल्कुल नहीं है। उन्होंने कीवर्ड staticऔर classकीवर्ड के बीच अंतर पूछा ।
डग मैकब्राइड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.