새로운 Apple Swift 언어로 무언가를 찾으려고합니다. Objective-C에서 다음과 같은 작업을 수행했다고 가정 해 봅시다. 내가 가진 readonly
속성을, 그들은 개별적으로 변경할 수 없습니다. 그러나 특정 방법을 사용하면 속성이 논리적으로 변경됩니다.
다음 예제를 보자. 매우 간단한 시계. 나는 Objective-C로 이것을 쓸 것이다.
@interface Clock : NSObject
@property (readonly) NSUInteger hours;
@property (readonly) NSUInteger minutes;
@property (readonly) NSUInteger seconds;
- (void)incrementSeconds;
@end
@implementation Clock
- (void)incrementSeconds {
_seconds++;
if (_seconds == 60) {
_seconds = 0;
_minutes++;
if (_minutes == 60) {
_minutes = 0;
_hours++;
}
}
}
@end
특정 목적을 위해 초, 분 및 시간을 직접 만질 수 없으며 방법을 사용하여 초 단위로만 증가시킬 수 있습니다. 이 방법 만 인스턴스 변수의 트릭을 사용하여 값을 변경할 수 있습니다.
스위프트에는 그러한 것이 없기 때문에 동등한 것을 찾으려고 노력하고 있습니다. 내가 이렇게하면 :
class Clock : NSObject {
var hours: UInt = 0
var minutes: UInt = 0
var seconds: UInt = 0
func incrementSeconds() {
self.seconds++
if self.seconds == 60 {
self.seconds = 0
self.minutes++
if self.minutes == 60 {
self.minutes = 0
self.hours++
}
}
}
}
작동하지만 누구나 속성을 직접 변경할 수 있습니다.
어쩌면 이미 Objective-C에서 디자인이 잘못되어 새로운 Swift에 해당하는 것이 적합하지 않은 이유입니다. 그렇지 않은 경우 누군가 대답이 있으면 매우 감사합니다.)
아마도 애플이 약속 한 미래의 액세스 제어 메커니즘 이 답일까요?
감사!
답변
다음과 private(set)
같이 속성 선언에 접두사를 붙이십시오 .
public private(set) var hours: UInt = 0
public private(set) var minutes: UInt = 0
public private(set) var seconds: UInt = 0
private
소스 파일에 internal
로컬로 유지하고 모듈 / 프로젝트에 로컬로 유지합니다.
private(set)
read-only
속성을 작성하는 동안 및 비공개로 private
설정합니다 .set
get
답변
원하는 것을 수행하는 두 가지 기본 방법이 있습니다. 첫 번째 방법은 개인 속성과 해당 속성을 반환하는 공용 계산 속성을 갖는 것입니다.
public class Clock {
private var _hours = 0
public var hours: UInt {
return _hours
}
}
그러나 “Swift Programming Language” 서적 의 “액세스 제어” 섹션에 설명 된 것과 같이 다른 방법으로 더 짧은 방법으로 달성 할 수 있습니다 .
public class Clock {
public private(set) var hours = 0
}
참고로, 공개 유형을 선언 할 때는 공개 이니셜 라이저를 제공해야합니다. 모든 속성에 기본값을 제공하더라도 init()
명시 적으로 public으로 정의해야합니다.
public class Clock {
public private(set) var hours = 0
public init() {
hours = 0
}
// or simply `public init() {}`
}
이것은 기본 이니셜 라이저에 대해 이야기 할 때 책의 같은 섹션에서 설명됩니다.
답변
액세스 제어가 없기 때문에 (발신자에 따라 다른 액세스 계약을 체결 할 수 없음을 의미) 다음은 현재 내가 수행 할 작업입니다.
class Clock {
struct Counter {
var hours = 0;
var minutes = 0;
var seconds = 0;
mutating func inc () {
if ++seconds >= 60 {
seconds = 0
if ++minutes >= 60 {
minutes = 0
++hours
}
}
}
}
var counter = Counter()
var hours : Int { return counter.hours }
var minutes : Int { return counter.minutes }
var seconds : Int { return counter.seconds }
func incrementTime () { self.counter.inc() }
}
이것은 단순히 카운터에 직접 액세스하기위한 수준의 간접적 인 추가를 추가합니다. 다른 클래스 는 Clock을 만든 다음 카운터에 직접 액세스 할 수 있습니다. 그러나 아이디어 , 즉 우리가 만들고자하는 계약은 다른 클래스가 Clock의 최상위 속성과 메서드 만 사용해야한다는 것입니다. 우리는 할 수 없습니다 그 계약을 집행 없지만 실제로 Objective-C에서도 시행하는 것은 거의 불가능했습니다.
답변
실제로 Swift에는 존재하지 않는 액세스 제어는 Objective C에서 생각하는 것처럼 시행되지 않습니다. 사람들 은 원하는 경우 읽기 전용 변수를 직접 수정할 수 있습니다 . 그들은 단지 클래스의 공개 인터페이스로는하지 않습니다.
Swift에서 비슷한 작업을 수행 할 수 있습니다 (코드 잘라 내기 및 붙여 넣기 및 일부 수정, 테스트하지 않았습니다).
class Clock : NSObject {
var _hours: UInt = 0
var _minutes: UInt = 0
var _seconds: UInt = 0
var hours: UInt {
get {
return _hours
}
}
var minutes: UInt {
get {
return _minutes
}
}
var seconds: UInt {
get {
return _seconds
}
}
func incrementSeconds() {
self._seconds++
if self._seconds == 60 {
self._seconds = 0
self._minutes++
if self._minutes == 60 {
self._minutes = 0
self._hours++
}
}
}
}
실제 저장된 속성이 공용 인터페이스에 표시된다는 점을 제외하고는 Objective C에있는 것과 동일합니다.
신속하게 목표 C에서도 할 수있는 더 흥미로운 것을 할 수는 있지만 신속하게 더 예쁘다 (브라우저에서 편집 했으므로 테스트하지 않았습니다).
class Clock : NSObject {
var hours: UInt = 0
var minutes: UInt {
didSet {
hours += minutes / 60
minutes %= 60
}
}
var seconds: UInt {
didSet {
minutes += seconds / 60
seconds %= 60
}
}
// you do not really need this any more
func incrementSeconds() {
seconds++
}
}