我正在尝试将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。这可能吗?
答案 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"