我是Swift的新手,想要使用像这样的实例方法初始化对象的成员变量:
class MyClass {
var x: String
var y: String
func createY() -> String {
self.y = self.x + "_test" // this computation could be much more complex
}
init(x: String) {
self.x = x
self.y = self.createY()
}
}
基本上,我不想在init
方法中内联所有初始化代码,而是将y
的初始化代码提取到专用方法createY
并调用此实例方法{{1在createY
中。但是,Swift编译器(Xcode 6.3 beta中的Swift 1.2编译器)抱怨道:
在super.init初始化self
之前,在方法调用'xxx'中使用'self'
这里'xxx'是实例方法的名称(createY)。
我可以理解Swift编译器正在抱怨什么以及它想要解决的潜在问题。但是,我不知道如何解决它。什么应该是Swift在init
中调用初始化代码的其他实例方法的正确方法?
目前,我使用以下技巧作为解决方法,但我不认为这是解决此问题的惯用方法(此解决方法需要使用init
而不是{{y
声明var
1}}这让我感到不安):
let
任何评论都表示赞赏。感谢。
答案 0 :(得分:10)
将createY()
转换为接受x
作为参数的全局或类函数,并返回y
。
func createY(x: String) -> String {
return x + "_test" // this computation could be much more complex
}
然后从您的init
正常调用它。
class MyClass {
let x: String
let y: String
init(x: String) {
self.x = x
self.y = createY(x)
}
}
答案 1 :(得分:2)
我认为Swift的方法是使用Computed Properties(https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html)
修改强>
您可以使用计算属性来代替调用函数来修改set / get上的属性:
class MyClass {
var x: String?
var y: String? {
get {
return "\(x!)_test"
}
}
init(x: String!){
self.x = x
}
}
let myClass = MyClass(x: "string")
print(myClass.y!) #=> "string_test"
答案 2 :(得分:2)
在Swift 3中,我一直在使用这种模式,
class MyClass {
var x: String?
private(set) lazy var y: String? = self.createY()
init(x: String){ self.x = x }
private func createY() -> String?
{
return "\(x ?? "nil") test"
}
}
这里的秘诀是使用private(set) lazy
。这样,您就可以将您的媒体资源标记为var
。并且lazy
将延迟初始化,直到您的init
函数完成。使用private(set)
仅允许此类中的函数修改该属性,包括lazy
关键字,但不允许公共接口更改它。当然,如果您希望界面更改您的媒体资源,那么您也可以将其标记为internal
(默认)或public
。但您需要将其标记为lazy var
答案 3 :(得分:1)
回答here,创建一个类函数。我添加了完整的代码。
class MyClass {
var x: String
var y: String
class func createY(x: String) -> String {
return x + "_test" // this computation could be much more complex
}
init(x: String) {
self.x = x
self.y = MyClass.createY(x)
}
}
答案 4 :(得分:0)
您可以使用此方法
类MyClass:NSObject {
let x: String
var y: String
init(x: String) {
self.x = x
self.y = self.x + "_test"
print(self.x)
print(self.y)
}
}
答案 5 :(得分:0)
Set-SPCustomLayoutsPage -Identity AccessDenied -RelativePath "/_layouts/custompages/myaccessdenied.aspx" -WebApplication "http://server_name/mywebapp"
答案 6 :(得分:0)
请参见Two-Phase Initialization和示例: https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html#ID52 在无主引用和隐式展开的可选属性中
class Country {
let name: String
var capitalCity: City!
init(name: String, capitalName: String) {
self.name = name
self.capitalCity = City(name: capitalName, country: self)
}
}
class City {
let name: String
unowned let country: Country
init(name: String, country: Country) {
self.name = name
self.country = country
}
}
要在两个类之间建立相互依赖关系,City的初始化程序将使用一个Country实例,并将该实例存储在其country属性中。
从Country的初始化程序中调用City的初始化程序。但是,Country的初始化程序无法将自身传递给City初始化程序,直到完全初始化了新的Country实例为止,如两阶段初始化中所述。
为满足此要求,您将Country的capitalCity属性声明为一个隐式展开的可选属性,由其类型注释(City!)末尾的感叹号指示。这意味着与任何其他可选参数一样,capitalCity属性的默认值为nil,但是无需进行隐式解包的可选参数中所述的解包即可访问它。
由于capitalCity具有默认的nil值,因此,一旦Country实例在其初始值设定项中设置其name属性,便认为该Country实例已完全初始化。这意味着一旦设置了name属性,Country初始化器就可以开始引用并传递隐式的self属性。因此,当Country初始化器设置自己的capitalCity属性时,Country初始化器可以将self作为City初始化器的参数之一传递。
因此添加y类型的感叹号-> var y: String!