Swift 클래스의 정적 및 클래스 함수 / 변수?


416

다음 코드는 Swift 1.2에서 컴파일됩니다.

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

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

정적 함수와 클래스 함수 의 차이점은 무엇입니까 ? 어느 것을 언제 사용해야합니까?

다른 변수를 정의하려고하면 다음 class var myVar2 = ""과 같이 말합니다.

클래스에서 아직 지원되지 않는 클래스 저장 속성; '정적'을 의미 했습니까?

이 기능이 지원 될 때 정적 변수와 클래스 변수 의 차이점은 무엇입니까 (즉, 둘 다 클래스에 정의 된 경우)? 어느 것을 언제 사용해야합니까?

(Xcode 6.3)


답변:


690

static그리고 class둘 다 메소드를 클래스의 인스턴스가 아닌 클래스와 연관시킵니다. 차이점은 서브 클래스가 class메소드 를 대체 할 수 있다는 것입니다 . static메소드를 대체 할 수 없습니다 .

class 프로퍼티는 이론적으로 같은 방식으로 작동하지만 (서브 클래스가이를 오버라이드 할 수는 있지만) 스위프트에서는 아직 불가능합니다.


89
final class클래스 내에서 함수와 '정적'함수 의 차이점은 무엇 입니까?
hippo_san

57
@hippo_san은 기본 클래스에서 기능적으로 동일합니다. 그러나 final서브 클래스에서 사용될 때 추가 대체를 차단하는 데 사용할 수 있습니다. 두 가지 모두 자신의 위치를 ​​가지고 있습니다 . 클래스 함수에서 사용 static하거나 final사용할 때 사소하고 스타일 선택에 달려 있다고 말합니다.
앤드류 로빈슨

8
아, 그래서 static func foo(){}Swift public static final foo(){}에서 Java 와 비슷 합니까?
Supuhstar

3
@Supuhstar : 기본적으로 그렇습니다.
mipadi

2
@mipadi 나는 지금 이해한다. 클래스 함수의 경우 "정적"을 "최종 클래스"로 바꿀 수 있지만 클래스의 특성의 경우 클래스 특성 대신 정적 특성 만 가질 수 있습니다. 따라서 "정적"키워드는 여전히 유효합니다.
allenlinli

72

놀이터에 대한 mipadi의 답변과 의견을 시도했습니다. 그리고 그것을 공유 할 생각. 여기 요 mipadi의 대답은 받아 들인 것으로 표시되어야한다고 생각합니다.

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(){

    }
}

27

OOP 와 관련 하여 대답은 너무 간단합니다.

서브 클래스는 클래스 메소드 를 대체 할 수 있지만 정적 메소드는 대체 할 수 없습니다 .

게시물 외에도 클래스 변수 를 선언 하려면 (처럼 class var myVar2 = "") 다음과 같이해야합니다.

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

23

내 프로젝트 중 하나 에서이 혼란을 겪었 으며이 게시물이 매우 유용하다는 것을 알았습니다. 내 놀이터에서 똑같이 시도했고 여기에 요약이 있습니다. 이 저장 특성과 유형의 기능을 가진 사람 도움이되기를 바랍니다 static, final, class, 오버라이드 (override) 클래스는 바르 등

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"
    }
}

다음은 테스트 샘플입니다.

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

23

Swift 4의 테스트는 시뮬레이터의 성능 차이를 보여줍니다. "class func"로 수업을 만들고 "static func"로 구조체를 만들어 테스트에서 실행했습니다.

정적 기능은 다음과 같습니다.

  • 컴파일러 최적화없이 20 % 빨라짐
  • 최적화-전체 모듈 최적화가 활성화되면 38 % 더 빠릅니다.

그러나 iOS 10.3의 iPhone 7에서 동일한 코드를 실행하면 정확히 동일한 성능을 나타냅니다.

다음은 Swift 4에서 Xcode 9 용 샘플 프로젝트입니다. https://github.com/protyagov/StructVsClassPerformance


시뮬레이터 또는 물리적 장치에 있었습니까?
mmr118


7

정적 응답은 정적 디스패치입니다. 정적 메소드는 정적 메소드를 재정의 할 수 없기 때문에 런타임에 어떤 메소드가 실행 될지 알 수 있습니다.


0

차이점이 하나 더 있습니다. 클래스는 계산 된 유형의 유형 특성을 정의하는 데만 사용할 수 있습니다. 저장된 유형 속성이 필요한 경우 대신 static을 사용하십시오.

클래스 :-참조 유형

struct :-값 유형


0

classReference Type(클래스) 내부에서 사용됩니다 .

  • 계산 된 속성
  • 방법
  • 수있는 서브 클래스에 의해 오버라이드 (override) 할 수

static내부 Reference TypeValue Type(클래스, 열거 형)에 사용됩니다.

  • 계산 된 속성 및 저장된 속성
  • 방법
  • 서브 클래스로 변경할 수 없습니다
protocol MyProtocol {
//    class var protocolClassVariable : Int { get }//ERROR: Class properties are only allowed within classes
    static var protocolStaticVariable : Int { get }

//    class func protocolClassFunc()//ERROR: Class methods are only allowed within classes
    static func protocolStaticFunc()
}

struct ValueTypeStruct: MyProtocol {
    //MyProtocol implementation begin
    static var protocolStaticVariable: Int = 1

    static func protocolStaticFunc() {

    }
    //MyProtocol implementation end

//    class var classVariable = "classVariable"//ERROR: Class properties are only allowed within classes
    static var staticVariable = "staticVariable"

//    class func classFunc() {} //ERROR: Class methods are only allowed within classes
    static func staticFunc() {}
}

class ReferenceTypeClass: MyProtocol {
    //MyProtocol implementation begin
    static var protocolStaticVariable: Int = 2

    static func protocolStaticFunc() {

    }
    //MyProtocol implementation end

    var variable = "variable"

//    class var classStoredPropertyVariable = "classVariable"//ERROR: Class stored properties not supported in classes

    class var classComputedPropertyVariable: Int {
        get {
            return 1
        }
    }

    static var staticStoredPropertyVariable = "staticVariable"

    static var staticComputedPropertyVariable: Int {
        get {
            return 1
        }
    }

    class func classFunc() {}
    static func staticFunc() {}
}

final class FinalSubReferenceTypeClass: ReferenceTypeClass {
    override class var classComputedPropertyVariable: Int {
        get {
            return 2
        }
    }
    override class func classFunc() {}
}

//class SubFinalSubReferenceTypeClass: FinalSubReferenceTypeClass {}// ERROR: Inheritance from a final class

[참조 대 값 유형]

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.