在易碎的初始化器Swift 1.2中分配let变量 [英] Assigning let variable in fallible initializer swift 1.2

查看:157
本文介绍了在易碎的初始化器Swift 1.2中分配let变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有错误初始化程序的结构,而不是实例方法,而是一个初始化程序.更新到1.2后,当我尝试在初始化程序内分配let属性时,收到以下错误Cannot assign to 'aspectRatio' in self.我的代码如下:

I have a struct with a fallible initializer, not an instance method, but an initializer. After updating to 1.2, when I try to assign a let property inside the initializer, I receive the following error Cannot assign to 'aspectRatio' in self. My code below:

import Foundation

public struct MediaItem
{
public let url: NSURL!
public let aspectRatio: Double

public var description: String { return (url.absoluteString ?? "no url") + " (aspect ratio = \(aspectRatio))" }

// MARK: - Private Implementation

init?(data: NSDictionary?) {
    var valid = false
    if let urlString = data?.valueForKeyPath(TwitterKey.MediaURL) as? NSString {
        if let url = NSURL(string: urlString as String) {
            self.url = url
            let h = data?.valueForKeyPath(TwitterKey.Height) as? NSNumber
            let w = data?.valueForKeyPath(TwitterKey.Width) as? NSNumber
            if h != nil && w != nil && h?.doubleValue != 0 {
                aspectRatio = w!.doubleValue / h!.doubleValue
                valid = true
            }
        }
    }
    if !valid {
        return nil
    }
}

struct TwitterKey {
    static let MediaURL = "media_url_https"
    static let Width = "sizes.small.w"
    static let Height = "sizes.small.h"
}
}

我的问题是如何解决此问题?

My question is what do I do to fix this?

推荐答案

Swift 1.2解决了与let属性有关的漏洞:

Swift 1.2 has closed a loophole having to do with let properties:

新规则是,let常数必须在使用前进行初始化(如var),并且只能进行初始化,初始化后不得对其进行重新分配或更改.

The new rule is that a let constant must be initialized before use (like a var), and that it may only be initialized, not reassigned or mutated after initialization.

该规则正是您要违反的规则. aspectRatiolet属性,并且您已经在其声明中为其赋予了一个值:

That rule is exactly what you are trying to violate. aspectRatio is a let property and you have already given it a value in its declaration:

public let aspectRatio: Double = 0

因此,在进入初始化程序之前,aspectRatio的初始值为0.这是它唯一可以拥有的值.新规则意味着您不能永远再分配给aspectRatio,甚至不能在初始化器中 .

So before we ever get to the initializer, aspectRatio has its initial value — 0. And that is the only value it can ever have. The new rule means that you can never assign to aspectRatio ever again, not even in an initializer.

解决方法是(并且这始终是正确的方法):在其声明中为其分配 no 值:

The solution is (and this was always the right way): assign it no value in its declaration:

public let aspectRatio: Double

现在,在初始化程序中, 将其分配为0 将其分配为w!.doubleValue / h!.doubleValue.换句话说,请注意初始化程序一次中的个可能性.这将是您为aspectRatio赋值的唯一时间,一种或另一种方式.

Now, in the initializer, either assign it 0 or assign it w!.doubleValue / h!.doubleValue. In other words, take care of every possibility in the initializer, once. That will be the only time, one way or another, that you get to assign aspectRatio a value.

如果您考虑一下,您将意识到这是一种更加明智和一致的方法.以前,您有点不了解let的含义,而新规则正确地阻止了您这样做.

If you think about it, you'll realize that this is a much more sensible and consistent approach; previously, you were sort of prevaricating on the meaning of let, and the new rule has stopped you, rightly, from doing that.

在代码重写中,您在打算纾困并返回nil的情况下无法初始化所有属性.我知道这似乎违反直觉,但您不能这样做.您必须初始化所有属性,即使您打算纾困.我在我的书中非常清晰地讨论了 :

In your rewrite of the code, you are failing to initialize all properties in the situation where you intend to bail out and return nil. I know it may seem counterintuitive, but you cannot do that. You must initialize all properties even if you intend to bail out. I discuss this very clearly in my book:

一个失败的类初始化程序要等到它完成所有自己的初始化任务后才能说出return nil.因此,例如,一个失败的子类指定的初始化程序必须确保所有子类的属性都已初始化,并且必须先调用super.init(...),然后才能说出return nil. (这里有一个讽刺的味道:在将实例拆除之前,初始化程序必须完成实例的构建.)

A failable class initializer cannot say return nil until after it has completed all of its own initialization duties. Thus, for example, a failable subclass designated initializer must see to it that all the subclass’s properties are initialized and must call super.init(...) before it can say return nil. (There is a certain delicious irony here: before it can tear the instance down, the initializer must finish building the instance up.)

编辑:请注意,从Swift 2.2开始,将取消此要求.初始化属性return nil 之前是合法的.这将使类初始化程序与已经合法的struct初始化程序相提并论.

Please note that starting in Swift 2.2, this requirement will be lifted. It will be legal to return nil before initializing properties. This will put class initializers on a par with struct initializers, where this was already legal.

这篇关于在易碎的初始化器Swift 1.2中分配let变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆