bestsource

Swift에서 static func와 class func의 차이점은 무엇입니까?

bestsource 2023. 4. 24. 23:40
반응형

Swift에서 static func와 class func의 차이점은 무엇입니까?

Swift 라이브러리에서 다음 정의를 볼 수 있습니다.

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

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

와 멤버 함수는 가 있나요?static func, 「」라고 되어 있는 도 있습니다.class func하게 그런가요?static및 기능 및 Enum을 위한 것입니다.class업이나프 로로로? 용용? 용???또알 야이 ?이 이? ?? ??구문 자체에서 이러한 차이를 갖는 근거는 무엇입니까?

좀 더 명확히 하기 위해 예를 하나 들겠습니다.

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

렇기문 because because이다.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"
    }
}

스태틱은 구조 및 Enum의 정적 기능, 클래스는 클래스 및 프로토콜에 대한 정적 기능뿐입니까?

그게 가장 큰 차이점이에요.다른 차이점은 클래스 함수가 동적으로 디스패치되어 서브클래스에 의해 덮어쓸 수 있다는 것입니다.

프로토콜은 class 키워드를 사용하지만 프로토콜 구현에서 구조체를 제외하지 않고 대신 정적만 사용합니다.static 또는 클래스를 나타내기 위해 세 번째 키워드가 필요하지 않도록 프로토콜로 클래스를 선택했습니다.

Chris Latner가 이 토픽을 소개합니다.

구문(키워드로서 「type」을 사용하는 등)을 통일하는 것을 검토했습니다만, 실제로는 그렇게 간단하지 않습니다."class" 및 "static" 키워드는 친숙함에 도움이 되며 (+ 메서드의 구조를 이해한 후) 매우 알기 쉽고, 클래스에 진정한 스태틱 메서드를 추가할 수 있는 가능성이 있습니다.이 모델의 가장 이상한 점은 프로토콜이 키워드를 선택해야 한다는 것입니다(그리고 우리는 "클래스"를 선택했습니다). 그러나 결과적으로 올바른 트레이드오프입니다.

다음은 클래스 함수의 오버라이드 동작을 보여주는 토막입니다.

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

나는 운동장에서 몇 가지 실험을 했고 몇 가지 결론을 얻었다.

TL;DR 여기에 이미지 설명 입력

바와 같이, 시는와 의 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."

속성을 에 ""를 붙입니다.static는 타입 을 「」으로 마크 할 수 .class대신 선언 수식자를 지정하면 하위 클래스가 슈퍼 클래스의 구현을 재정의할 수 있습니다.이치노

메모
클래스 선언에서 키워드는static선언에 마크를 붙이는 것과 같은 효과가 있습니다.class그리고.final선언 수식자

출처: Swift Programming Language - 유형 변수 속성

static 키워드와 class 키워드를 모두 사용하면 메서드를 클래스의 인스턴스가 아닌 클래스에 부가할 수 있습니다.예를 들어 이름 및 연령과 같은 속성을 사용하여 Student 클래스를 만든 다음 개별 인스턴스가 아닌 Student 클래스 자체에서 소유하는 정적 메서드 numberOfStudents를 만들 수 있습니다.

스태틱과 클래스는 상속을 지원하는 방법이 다릅니다.정적 메서드를 만들면 해당 메서드는 클래스가 소유하게 되어 하위 클래스에서 변경할 수 없지만 클래스를 사용하면 필요에 따라 재정의될 수 있습니다.

다음은 코드 예시입니다.

class Vehicle {
    static func getCurrentSpeed() -> Int {
        return 0
    }
    
    class func getCurrentNumberOfPassengers() -> Int {
        return 0
    } 
}

class Bicycle: Vehicle {
    //This is not allowed
    //Compiler error: "Cannot override static method"
    //static override func getCurrentSpeed() -> Int {
        //return 15
    //}
    
    class override func getCurrentNumberOfPassengers() -> Int {
        return 1
    }
}

이 예에서는 모든 측면이 지워집니다.

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.
 */

출력:

애플이 발간한 스위프트 2.2 북에 따르면:

"유형 메서드는 다음과 같이 적습니다.static키워드를 지정합니다.클래스에서는,class서브클래스가 해당 메서드의 슈퍼클래스의 구현을 덮어쓸있도록 하는 키워드입니다.

Swift 2.0부터 Apple은 다음과 같이 말합니다.

"프로토콜에서 속성을 정의할 때는 항상 static 키워드를 사용하여 접두사 유형 속성 요구사항을 지정하십시오.이 규칙은 유형 속성 요건을 클래스에 의해 구현될 때 class 키워드 또는 static 키워드로 프리픽스할 수 있는 경우에도 관련됩니다."

이것은 type 메서드라고 불리며 인스턴스 메서드와 같이 닷 구문을 사용하여 호출됩니다.단, 유형 메서드는 해당 유형의 인스턴스가 아닌 유형으로 호출합니다.SomeClass라는 클래스의 유형 메서드를 다음과 같이 호출합니다.

언급URL : https://stackoverflow.com/questions/25156377/what-is-the-difference-between-static-func-and-class-func-in-swift

반응형