[methods] 계산 된 읽기 전용 속성 대 Swift의 함수

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에서는 클래스가 수행하는 작업이 아니라 클래스의 속성 인 것이 합리적입니다 .
  • 간결성 / 명확성 -값을 가져올 때 빈 괄호를 사용할 필요가 없습니다.

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


NB 언뜻보기에 이것은 매우 일반적인 OOP 질문처럼 보이지만,이 언어를 사용할 때 모범 사례를 안내 할 스위프트 관련 기능을 알고 싶습니다.



답변

그것은 대부분 스타일의 문제인 것 같습니다. 나는 속성 을 사용하는 것을 강력히 선호 합니다 : 속성; 얻을 수있는 간단한 값을 의미합니다. 나는 실제 작업을 할 때 기능 (또는 방법)을 사용 합니다 . 디스크 나 데이터베이스에서 무언가를 계산하거나 읽어야 할 수도 있습니다.이 경우 간단한 값만 반환되는 경우에도 함수를 사용합니다. 이렇게하면 호출이 저렴한 지 (속성) 비용이 많이 드는지 (함수) 쉽게 확인할 수 있습니다.

Apple이 몇 가지 Swift 코딩 규칙을 게시하면 더 명확해질 것입니다.


답변

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

경우에 따라 인수가없는 함수는 읽기 전용 속성과 교환 할 수 있습니다. 의미는 비슷하지만 서로 선호하는시기에 대한 몇 가지 스타일 규칙이 있습니다.

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

  • 던지지 않는다
  • 복잡성은 계산하기가 저렴합니다 (또는 첫 번째 실행에서 계산 됨).
  • 호출에 대해 동일한 결과를 반환합니다.

답변

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

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에도 적용됩니다. 나는 당신이 얻는 속성으로

  • 하위 클래스에 setter를 추가하여 속성을 만들 가능성 readwrite
  • didSet변경 알림 을 위해 KVO /를 사용하는 기능
  • 보다 일반적으로 키 경로를 예상하는 메소드에 속성을 전달할 수 있습니다 (예 : 가져 오기 요청 정렬)

Swift에 특정한 것에 관해서는 제가 가진 유일한 예 @lazy는 속성에 사용할 수 있다는 것 입니다.


답변

차이점이 있습니다. 속성을 사용하면 결국이를 재정의하고 하위 클래스에서 읽기 / 쓰기로 만들 수 있습니다.


답변

읽기 전용의 경우, 선언을 삭제 하면 인스턴스 의 상태 를 구성하는 수량과 단순히 함수 인 수량 간의 구분이 모호해 지기 때문에 계산 된 속성이 메서드와 의미 적으로 동일하다고 간주 되어서는 안됩니다 . 상태. 호출 사이트에서 타이핑 을 저장 하지만 코드의 명확성을 잃을 위험이 있습니다.func()

간단한 예로 다음 벡터 유형을 고려하십시오.

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

길이를 메서드로 선언하면 xand에 의존하는 상태의 함수임을 분명히 알 수 y있습니다.

반면 length에 계산 된 속성 으로 표현한다면

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

당신의 인스턴스에 IDE에서 탭 완성 점 때 다음 VectorWithLengthAsProperty, 그것은 것처럼 보일 것이다 x, y, length개념적으로 잘못 동등한에 등록했다.


답변

일반 함수보다 계산 된 속성을 선호하는 상황이 있습니다. 예 : 사람의 전체 이름을 반환합니다. 이름과 성을 이미 알고 있습니다. 따라서 실제로 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