在Swift中覆盖或绕过访问器

时间:2015-12-18 12:41:12

标签: objective-c swift swift2 setter getter-setter

我试图在Swift中复制Objective-C的ivar / setter访问。 以下是Objective-C中setter与ivar使用的简单例子:

@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
@end


@implementation Person

- (void)setName:(NSString *)name {
    // Let's assume that this is an expensive operation.
    // I want to perform it only when necessary.
    _name = name.capitalizedString;
}

- (void)someMutatingMethod1
{
    Person *otherPerson = nil; // Get a person
    NSString *newName = otherPerson.name;

    // At this point, I know that newName is in the corect format because it comes from a Person object.
    // I don't need the expensive setter work, so I bypass it with direct ivar access.
    _name = newName;
}

- (void)someMutatingMethod2
{
    NSString *userInputName = @"john";

    // It's user input, I need the setter to perform it's work.
    self.name = userInputName;
}

@end

在Swift中复制此类的最接近的方法是:

class Person {
    private var _name: String?
    var name: String? {
        get {
            return _name
        }
        set (newName) {
            _name = newName?.capitalizedString
        }
    }

    func someMutatingMethod1() {
        let otherPerson:Person? = nil;
        _name = otherPerson?.name;
    }

    func someMutatingMethod2() {
        let userInputName = "john";
        self.name = userInputName;
    }

}

但这很痛苦,因为访问器不是自动合成的,我必须手动编写它们。而且令人困惑,因为我现在可以使用_namenameself._nameself.name

现在,Stack Overflow上的大多数答案都表明我写了这个:

class Person2 {
    var name: String? {
        didSet {
            self.name = self.name?.capitalizedString
        }
    }
}

但我认为这是令人困惑的,也不清楚我的意图。在设置名称属性之后,我没有尝试执行某些级联变异 ,我试图改变之前传递给setter 的值设置值。而且,我希望能够私下绕过这个设置器,而这种方法是不可能的。

为什么我不能写这个:

class Person3 {
    var name: String? {
        set (newName) {
            name = newName?.capitalizedString
        }
    }
}
// This one actually makes the compiler crash on Xcode 7.2 

或者这个:

class Person4 {
    var name: String?

    override func setName(newName) {
        name = newName?.capitalizedString
    }
}

甚至是这样:

class Person5 {
    var name: String? {
        willSet(newName) {
            return newName?.capitalizedString
        }
    }
}

我是否遗漏了某些东西,或者只是没有办法让Objective-C拥有相同的构造?

0 个答案:

没有答案