programing

Swift에서 계산된 읽기 전용 속성 vs 함수

codeshow 2023. 10. 9. 23:42
반응형

Swift에서 계산된 읽기 전용 속성 vs 함수

Swift WWDC description합니다가

class Vehicle {
    var numberOfWheels = 0
    var description: String {
        return "\(numberOfWheels) wheels"
    }
}

let vehicle = Vehicle()
println(vehicle.description)

대신 방법을 사용하는 것보다 위의 방법을 선택하는 것에 어떤 영향이 있습니까?

class Vehicle {
    var numberOfWheels = 0
    func description() -> String {
        return "\(numberOfWheels) wheels"
    }
}

let vehicle = Vehicle()
println(vehicle.description())

읽기 전용 계산 속성을 선택하는 가장 명확한 이유는 다음과 같습니다.

  • 의미론 - 이 예에서는 다음과 같이 설명할 수 있습니다.description그것이 수행하는 행위가 아닌, 클래스의 속성이 됩니다.
  • 간결성/명확성 - 값을 가져올 때 빈 괄호를 사용할 필요가 없습니다.

분명히 위의 예는 지나치게 단순하지만, 다른 예보다 하나를 선택해야 하는 다른 좋은 이유가 있습니까?예를 들어, 어떤 기능을 사용할지 결정하는 데 도움이 되는 기능이나 속성의 일부 기능이 있습니까?


N.B. 언뜻 보기에 이것은 꽤 흔한 OOP 질문처럼 보이지만, 저는 이 언어를 사용할 때 모범 사례를 안내해 줄 스위프트 고유의 기능에 대해 알고 싶습니다.

대부분 스타일의 문제인 것 같습니다.저는 속성을 사용하는 것을 매우 선호합니다. 속성은 여러분이 얻을 수 있는 단순한 값 및/또는 설정할 수 있는 단순한 값을 의미합니다.나는 실제 작업을 할 때 함수(또는 방법)를 사용합니다.디스크 또는 데이터베이스에서 무언가를 계산하거나 읽어야 할 수도 있습니다.이 경우 간단한 값만 반환되는 경우에도 함수를 사용합니다.이를 통해 통화가 저렴한지(재산)인지, 비싼지(기능)를 쉽게 파악할 수 있습니다.

Apple이 Swift 코딩 규약을 발표하면 더 명확해질 것입니다.

자, 당신은 Kotlin의 조언 https://kotlinlang.org/docs/reference/coding-conventions.html#functions-vs-properties 을 적용할 수 있습니다.

어떤 경우 인수가 없는 함수는 읽기 전용 속성과 호환될 수 있습니다.의미론은 비슷하지만, 언제 하나를 다른 것보다 선호할 것인지에 대한 양식적인 관습이 있습니다.

기본 알고리즘이 다음과 같은 경우 함수보다 속성을 선호합니다.

  • 던지지 않음
  • 복잡도는 계산하기에 저렴합니다(또는 첫 번째 런에서 с링됨)
  • 호출에 대해 동일한 결과를 반환합니다.

일반적으로 계산된 속성 대 방법에 대한 질문은 어렵고 주관적이지만, 현재 스위프트의 경우 속성보다 방법을 선호하는 것에 대한 중요한 주장이 하나 있습니다.속성에 맞지 않는 순수 함수(Swift 2.0 베타 기준)로 Swift의 메서드를 사용할 수 있습니다.이것은 기능적 구성에 참여할 수 있기 때문에 방법을 훨씬 더 강력하고 유용하게 만듭니다.

func fflat<A, R>(f: (A) -> () -> (R)) -> (A) -> (R) {
    return { f($0)() }
}

func fnot<A>(f: (A) -> Bool) -> (A) -> (Bool) {
    return { !f($0) }
}

extension String {
    func isEmptyAsFunc() -> Bool {
        return isEmpty
    }
}

let strings = ["Hello", "", "world"]

strings.filter(fnot(fflat(String.isEmptyAsFunc)))

차이가 있습니다.속성을 사용하면 속성을 재정의하고 하위 클래스에서 읽기/쓰기할 수 있습니다.

런타임이 동일하므로 이 질문은 Objective-C에도 적용됩니다.내 말은, 네가 얻은 재산으로

  • 을 화할 readwrite
  • KVO didSet
  • 일반적으로 키 경로를 예상하는 메소드에 속성을 전달할 수 있습니다(예: fetch request sorting).

말하자면,이 , 할 수 입니다.@lazy재산에 대하여

읽기 전용의 경우, 계산된 속성은 방법과 의미론적으로 동등한 것으로 간주되어서는 안 됩니다. 왜냐하면 그들이 동일하게 행동할 때에도.func선언은 인스턴스의 상태를 구성하는 양과 단지 상태의 함수인 양의 구분을 흐립니다.타이핑 저장()통화 현장에서, 하지만 코드의 명확성을 잃을 위험이 있습니다.

사소한 예로 다음과 같은 벡터 유형을 생각해 보겠습니다.

struct Vector {
    let x, y: Double
    func length() -> Double {
        return sqrt(x*x + y*y)
    }
}

으로써 으로써, 알 수 .x그리고.y.

에를 한다면,length

struct VectorWithLengthAsProperty {
    let x, y: Double
    var length: Double {
        return sqrt(x*x + y*y)
    }
}

를 도트 할 때VectorWithLengthAsProperty, 그럴 것처럼 보일 것입니다.x,y,length동일한 위치에 있는 속성들인데 개념적으로 틀렸습니다.

성능적인 측면에서 봤을 때는 차이가 없어 보입니다.벤치마크 결과에서 볼 수 있듯이.

요지를

main.swift코드 조각:

import Foundation

class MyClass {
    var prop: Int {
        return 88
    }

    func foo() -> Int {
        return 88
    }
}

func test(times: u_long) {
    func testProp(times: u_long) -> TimeInterval {
        let myClass = MyClass()
        let starting = Date()
        for _ in 0...times {
            _ = myClass.prop
        }
        let ending = Date()
        return ending.timeIntervalSince(starting)
    }


    func testFunc(times: u_long) -> TimeInterval {
        let myClass = MyClass()
        let starting = Date()
        for _ in 0...times {
            _ = myClass.prop
        }
        let ending = Date()
        return ending.timeIntervalSince(starting)
    }

    print("prop: \(testProp(times: times))")
    print("func: \(testFunc(times: times))")
}

test(times: 100000)
test(times: 1000000)
test(times: 10000000)
test(times: 100000000)

출력:

prop: 0.0380070209503174 func: 0.0350250005722046 prop: 0.371925950050354 func: 0.363085985183716 prop: 3.4023300409317 func: 3.38373708724976 prop: 33.5842199325562 func: 34.8433820009232 Program ended with exit code: 0

차트에서:

benchmark

일반 함수보다 계산된 특성을 선호하는 경우가 있습니다.예: 사람의 전체 이름을 반환합니다.당신은 이미 이름과 성을 알고 있습니다.로.fullName속성은 함수가 아닌 속성입니다.이 수 과 성을 할 수 다다)

class Person{
    let firstName: String
    let lastName: String
    init(firstName: String, lastName: String){
        self.firstName = firstName
        self.lastName = lastName
    }
    var fullName :String{
        return firstName+" "+lastName
    }
}
let william = Person(firstName: "William", lastName: "Kinaan")
william.fullName //William Kinaan

의미론적으로 계산된 속성은 개체의 고유 상태와 밀접하게 결합되어야 합니다. 다른 속성이 변경되지 않으면 다른 시간에 계산된 속성을 쿼리하면 해당 개체에서 순함수를 호출하는 것과 유사한 출력(== 또는 ===를 통해 compar 가능)을 얻을 수 있습니다.

반면에 방법은 우리가 항상 같은 결과를 얻지는 못할지도 모른다는 가정과 함께 나옵니다. 스위프트는 함수를 순수한 것으로 표시할 방법이 없기 때문입니다.또한 OOP의 메소드는 액션으로 간주되며, 이는 메소드를 실행하면 부작용이 발생할 수 있음을 의미합니다.방법에 부작용이 없으면 안전하게 계산된 속성으로 변환할 수 있습니다.

위의 두 문장 모두 순수하게 의미론적인 관점에서 작성된 것입니다. 계산된 속성에서 예상하지 못한 부작용이 발생할 수 있고 방법이 순수할 수도 있기 때문입니다.

역사적인 설명은 NSObject의 속성이며 많은 사람들이 Swift에서도 동일하게 유지될 것으로 예상할 것입니다.다음에 부모를 추가하면 혼란만 가중됩니다.

편집: 격렬한 반대 투표 후에 저는 무언가를 분명히 해야 합니다. 만약 그것이 점 구문을 통해 접근된다면, 그것은 재산으로 간주될 수 있습니다.후드 밑에 뭐가 있는지는 중요하지 않습니다.점 구문으로는 일반 메서드에 액세스할 수 없습니다.

게다가 이 부동산에 전화를 걸려면 스위프트의 경우처럼 부모가 따로 필요하지 않아서 혼란을 초래할 수 있습니다.

크리스티크의 제안을 반영한 벤자민 웬의 답변 업데이트/고정 버전.

class MyClass {varprop:int {return 88}

    func foo() -> Int {
        return 88
    }
}

func test(times: u_long) {
    func testProp(times: u_long) -> TimeInterval {
        let myClass = MyClass()
        let starting = CACurrentMediaTime()
        for _ in 0...times {
            _ = myClass.prop
        }
        let ending = CACurrentMediaTime()
        return ending - starting
    }

    func testFunc(times: u_long) -> TimeInterval {
        let myClass = MyClass()
        let starting = CACurrentMediaTime()
        for _ in 0...times {
            _ = myClass.foo()
        }
        let ending = CACurrentMediaTime()
        return ending - starting
    }
    
    print("prop: \(testProp(times: times))")
    print("func: \(testFunc(times: times))")
}

test(times: 100000)
test(times: 1000000)
test(times: 10000000)
test(times: 100000000)

언급URL : https://stackoverflow.com/questions/24035276/computed-read-only-property-vs-function-in-swift

반응형