Swift的新功能 - 可用的初始化程序

时间:2017-01-25 21:11:22

标签: java swift failable

我正在尝试将Java类转换为Swift:

// Card class with only a main function
public class Card {
// fields
private int numvalue;

// constructor(s)
public Card(int v) {
    if (v > 0 && v < 11) {
        this.numvalue = v;}
    else {
        System.out.println("Error: Card value is outside the allowed range.
        Value must be between 1 and 10 inclusive.")
    }

如果我尝试使用值不在1到10之间的构造函数初始化Card对象,则初始化失败,并在终端中打印一条语句,说明该值不在可接受的范围内。我试图在Swift中重新创建它。

class Card {
    var numValue : Int?
    init(numValue:Int) {
        if (numValue > 0 && numValue < 11) {self.numValue = numValue}
        else {print("Card value must be between 0 and 11")}
    }
    func setNumValue(value:Int) -> () {
        self.numValue = value
    }
    func getNumValue() -> Int {
        return self.numValue!
    }
}

以上在适当的情况下工作,但即使传递了不可接受的值,它仍然会创建一个Card实例,因为我仍然可以使用setNumValue(value :)方法来更改值。

我尝试使init(numvalue :)方法可用,但如果初始化成功,我会得到一个Optional(Card)。理想情况下,我希望任何成功初始化的Card对象都是Card对象,而不是包含Card的Optional。这可能吗?

3 个答案:

答案 0 :(得分:2)

嗯,您必须检查返回的Optional是否为nil,然后将其解包为非可选项:

class Card {
    var numValue : Int
    init?(numValue:Int) {
        guard (numValue > 0 && numValue < 11) else {
            print("Card value must be between 0 and 11")
            return nil
        }

        self.numValue = numValue
    }
    func setNumValue(value:Int) -> () {
        guard (numValue > 0 && numValue < 11) else {
            print("Card value must be between 0 and 11")
            return
        }
        self.numValue = value
    }
    func getNumValue() -> Int {
        return self.numValue
    }
}


let cOk = Card(numValue:1)
let cFails = Card(numValue:-1)

if let c = cOk {
    // now work with c because it's a Card,
    // not an Optional<Card> 
}

答案 1 :(得分:1)

  

理想情况下,我希望任何成功初始化的Card对象都是Card对象,而不是包含Card的Optional。这可能吗?

使用Swift中提供的标准初始化方案是不可能的。如果在某些条件下初始化失败,最终会得到Optional<Card>

可用的初始化

您可以通过在?关键字的末尾添加init来启用初始值设定项。那是init?

这表示初始化程序可能失败(返回nil)。

在初始化程序中,当您不满足创建实例的条件时,您可以返回nil。

在这种情况下,我使用guard语句,但您也可以使用if语句。

class Card {
    var numValue : Int?

    init?(numValue: Int) {
        guard numValue > 0 && numValue < 11 else {
            print("Card value must be between 0 and 11")
            return nil
        }
        self.numValue = numValue
    }

    func setNumValue(value:Int) -> () {
        self.numValue = value
    }

    func getNumValue() -> Int {
        return self.numValue!
    }
}

由于您现在正在返回Card的可选实例,因此您可以使用if let安全地解包可选项并对该实例执行某些操作,或者处理未成功创建实例的事实(你有一个零。

let card = Card(numValue: 12)
if let card = card {
    print(card)
} else {
    print("Unable to create a Card instance")
}

在上面的示例中,将打印“无法创建卡实例”字符串(除了“卡片值必须介于0和11之间”)。

有关如何在Swift中进行可初始化工作的更多信息,请访问here

答案 2 :(得分:1)

如果您的对象类型不需要持久化,则应使用Struct。 BTW无需将value属性变为变量,并创建仅更改其属性的方法。您只需创建一个新的Card对象来替换它而不是更改旧的。

您的卡片结构应如下所示:

struct Card {
    let value: Int
    init?(value: Int) {
        guard 1...10 ~= value else {
            print("Card value is out of range 1...10")
            return nil
        }
        self.value = value
    }
}

let card = Card(value: 2)       // returns an object of optional type (Card?)   "optional Card(value: 10)\n"
let nilCard = Card(value: 11)   // valus out of the range 1...10 will return nil

if let card = Card(value: 10)  {
    print(card)   // "Card(value: 10)\n"
}
  

我希望任何成功初始化的Card对象都是一张卡片   对象,而不是包含卡的可选项。这可能吗?

是的,这是可能的。只需为初始化程序添加一个前置条件,并使其不可用:

struct Card {
    let value: Int
    init(value: Int) {
        precondition(1...10 ~= value, "Card value is out of range 1...10")
        self.value = value
    }
}


let card = Card(value: 2)                // returns an object of type (Card)   "Card(value: 2)\n"
let cantInitCard = Card(value: 11)       // won't execute (precondition not met range 1...10)

您还可以为卡片初始化程序添加第二个参数范围(可选,因为您可以设置默认值),并为卡片添加范围属性,以便查看可能的卡片值:

struct Card {
    let value: Int
    let range: ClosedRange<Int>
    init(value: Int, range: ClosedRange<Int> = 1...10) {     // you can set a default range for yor cards
        precondition(range ~= value, "Card value is out of range: " + range.description)
        self.value = value
        self.range = range
    }
}

let card = Card(value: 5)       // returns an object of type (Card) "Card(value: 5, range: 1...10)\n"
print(card.value, card.range)   // "5 1...10\n"

如果您想要一张卡片的值范围为1 ... 13,则只需通过范围

let newCard = Card(value: 11,  range: 1...13)    // ok to execute (precondition met range 1...13) 
print(newCard.value, newCard.range)              // "11 1...13\n"