什么是"自我"用于Swift?

时间:2014-11-10 00:26:38

标签: ios swift self

我是Swift的新手,我想知道self的用途和原因。

我已经在类和结构中看到了它,但我真的发现它们不是必需的,甚至没有必要在我的代码中提及它们。它们用于什么以及为什么?在什么情况下有必要使用它?

我一直在阅读这个问题的很多问题和答案,但是没有一个能完全回答我的问题,他们总是倾向于将它与this进行比较,就像在Java中一样,我对此并不熟悉。< / p>

9 个答案:

答案 0 :(得分:60)

更新:2015年11月24日

是的,它与 Java 中的this Objective-C 中的self相同,但 Swift ,self仅在从闭包中调用属性或方法或区分代码中的属性名称时才需要(例如初始值设定项)。因此,除非您通过闭包进行调用,否则您可以安全地使用几乎所有类组件而不使用self。

  

“self属性类型的每个实例都有一个隐含属性   名为self,与实例本身完全等效。您   使用self属性来引用其中的当前实例   自己的实例方法。

     

上面示例中的increment()方法可能已经写好了   像这样:

func increment() {
    self.count++
}
     

实际上,您不需要经常在代码中编写self。   如果你没有明确地写self,Swift假定你是   无论何时你指的是当前实例的属性或方法   在方法中使用已知的属性或方法名称。这个假设   通过使用count(而不是self.count)来证明   在Counter的三个实例方法中。

     

当一个参数名称出现时,会出现此规则的主要异常   instance方法与该实例的属性同名。在   在这种情况下,参数名称优先,它变为   必须以更合格的方式提及房产。你用   self属性,用于区分参数名称和   财产名称。

     

此处,self消除了名为x的方法参数和。x之间的歧义   一个也称为self的实例属性:“

摘录自:Apple Inc.“The Swift Programming Language(Swift 2 Prerelease)。”


这是Ray Wenderlich建议在Swift中使用class BoardLocation { let row: Int, column: Int init(row: Int, column: Int) { self.row = row self.column = column let closure = { println(self.row) } } } 作为教程的方法:

使用自我

为简明起见,请避免使用self,因为Swift不要求它访问对象的属性或调用其方法。

在需要时使用self来区分初始值设定项中的属性名和参数,以及在闭包表达式中引用属性时(根据编译器的要求):

self

这是GitHub关于self申请的{{3}}建议:

仅在需要时明确引用self

访问self上的属性或方法时,默认情况下隐含对private class History { var events: [Event] func rewrite() { events = [] } } 的引用:

extension History {
    init(events: [Event]) {
        self.events = events
    }

    var whenVictorious: () -> () {
        return {
            self.rewrite()
        }
    }
}

仅在语言需要时包含explicit关键字 - 例如,在闭包中或参数名称冲突时:

{{1}}

理由:这使得self的捕获语义在闭包中更突出,并避免了其他地方的冗长。

答案 1 :(得分:25)

创建扩展程序时,您也会经常使用自我,例如:

extension Int {
    func square() -> Int {
        return self * self
    }

    // note: when adding mutating in front of it we don't need to specify the return type
    // and instead of "return " whatever
    // we have to use "self = " whatever

    mutating func squareMe() {
        self = self * self
    }
}
let x = 3
let y = x.square()  
println(x)         // 3
printlx(y)         // 9

现在假设您想要更改var结果本身 你必须使用变异函数来自行更改

var z = 3

println(z)  // 3

现在让它变异

z.squareMe()

println(z)  // 9

//现在让我们看一下使用字符串的另一个例子:

extension String {
    func x(times:Int) -> String {
        var result = ""
        if times > 0 {
            for index in 1...times{
                result += self
            }
            return result
        }
        return ""
    }

    // note: when adding mutating in front of it we don't need to specify the return type
    // and instead of "return " whatever
    // we have to use "self = " whatever

    mutating func replicateMe(times:Int){
        if times > 1 {
            let myString = self
            for index in 1...times-1{
                self = self + myString
            }
        } else {
            if times != 1 {
                self = ""
            }
        }
    } 
}


var myString1 = "Abc"
let myString2 = myString1.x(2)

println(myString1)         // "Abc"
println(myString2)         // "AbcAbc"

现在让我们改变myString1

myString1.replicateMe(3)

println(myString1)         // "AbcAbcAbc"

答案 2 :(得分:16)

  

在什么情况下有必要使用它

仅当局部变量的名称掩盖了属性的名称时才使用必要

但是,作为 style (和可读性)的问题,我总是使用它:

  • 我将它与属性名称一起使用,因为否则我不知道这个变量是什么(因为它既不是本地声明也不是传入参数)。

  • 我将它用作函数(方法)调用的接收者,以便将这些方法与顶级函数或本地函数区分开来。

答案 3 :(得分:10)

我要谈谈我们为什么需要self

当我们定义一个类时,例如:

class MyClass {
    func myMethod()
}

我们正在创建类对象。是的,Class也是一个对象。

然后,无论使用该类创建了多少个实例,所有实例都将具有其类对象的引用点。

您可以想象由Class定义的所有实例方法都在Class对象中,并且只有一个副本。

enter image description here

这意味着使用Class创建的所有实例都共享相同的方法。

现在想象您是类对象中的myMethod,并且因为您为所有实例共享,所以您必须有办法知道您正在处理哪个实例。

当有人说instance1.myMethod()时,就意味着&#34;嗨! myMethod,请完成您的工作,instance1是您正在处理的对象&#34;。

如何引用呼叫者发送给您的对象,使用self

如果我错了,请纠正我,谢谢。

  

“在实践中,您不需要经常在代码中编写self。如果   你没有明确地写自己,Swift假设你是指   当你使用a时,到当前实例的属性或方法   方法中的已知属性或方法名称。“

     

摘自:Apple Inc.“The Swift Programming Language。”iBooks。   https://itun.es/tw/jEUH0.l

答案 4 :(得分:7)

首先:这里已经发布了很好的答案,例子和解释,但我必须指出一些事情:

保留字:swift中的self类似于this ,但它与Java或Javascript 中的不一样。

@Dave Gomez正确引用:

  

一个类型的每个实例都有一个名为self的隐式属性,它与实例本身完全等效。

这里开始了一个主要的区别,因为:

  1. swift中的“每个实例”(至少现在)几乎是 Every-thing
  2. 在Java(例如)中,您只能在实例范围内使用单词this,在swift中,您几乎可以使用 Every-where
  3. 以下是一些例子:

    //Example 1:
    var x="foo"
    x.self="bar".self//compiles and run
    
    //Example 2:
    print.self(x);//compiles and run
    
    //Example 3:
    func myOther(self otherSelf:Person){}
    myOther(self: personObject);//compiles and run
    
    //Example 4:
    class Foo{
          var bar=""
          init(){
              self.addSome()//this would be the same in Java
          }
          func addSome(){
              //But definitely not this:
              self.self.bar.self.self="some".self.self
          }
    }
    //Guess what - also compiles and run...
    let f=Foo()
    print(f.bar)
    

    如果您想了解更多信息,请参阅:Why 'self.self' compiles and run in swift

    OP问题是关于swift的内容,所以我不会向读者解释它在Java或Javascript中的含义(但如果有些读者需要它只是写评论)。

答案 5 :(得分:3)

以下文章详细解释了public function getBy($column, $value) { try { return User::where($column, $value)->first(); } catch(Exception $e) { throw new Exception("Model Not Found"); } }

How to use correctly 'self' keyword in Swift

self是实例上引用自身的属性。它用于访问方法中的类,结构和枚举实例。

当以类型方法(selfstatic func)访问self时,它指的是实际类型(而不是实例)。

当您想要访问实例属性时,Swift允许省略class func

当method参数与instance属性同名时,必须明确使用self进行区分。 请注意,方法参数优先于实例属性。

答案 6 :(得分:1)

我一般都是编码方面的菜鸟-尽管这些答案很棒,但从一个总菜鸟的角度来看,他只是希望在没有所有这些困难的单词和概念的情况下尽可能地实际回答,这是我的超级菜鸟傻了下版本:

使用

'self'是因为如果您在函数范围内键入变量,编码应用程序将不知道使用哪个变量。这与范围有关,如果其他变量具有相同的名称,则可以清楚地说明您正在使用哪个变量。范围是大括号{}中的区域。例如:

{ scope1 {scope2} }

这里您不需要使用自己:

class example {
    private var exampleVar = “this is the class scope variable”

    func x() {
        //You don't have to use self here
        print(exampleVar)
    }
}

这里您需要使用self:

class example {
        private var exampleVar = “this is the class scope variable”

        func x(_ exampleVar: String) {
            //It would be confusing which exampleVar is used here so you should use self
            print(exampleVar)
            print(self.exampleVar)
        }
}

还有这种情况:

class example {
    private var exampleVar = “this is the class scope variable”

    func x() {
        randomMethod { _ in
            //This is not the class scope here, so we need to use self here.
            //You will be flagged during build time of this if you don't use self.
            print(self.exampleValue)                     
        }
    }
}

答案 7 :(得分:0)

self是引用自身的实例的属性。它用于访问方法中的类,结构和枚举实例。 当方法参数的名称与实例属性的名称相同时,必须显式使用self.myVariable = myVariable进行区分。 请注意,方法参数的优先级高于实例属性。

    struct Weather {
let windSpeed: Int
  let chanceOfRain: Int
  init(windSpeed: Int, chanceOfRain: Int) {
    self.windSpeed = windSpeed
    self.chanceOfRain = chanceOfRain
  }

  func isDayForWalk() -> Bool {
    let comfortableWindSpeed = 5
    let acceptableChanceOfRain = 30
    return self.windSpeed <= comfortableWindSpeed
      && self.chanceOfRain <= acceptableChanceOfRain
  }

}
// A nice day for a walk
let niceWeather = Weather(windSpeed: 4, chanceOfRain: 25)  
print(niceWeather.isDayForWalk()) // => true

答案 8 :(得分:0)

我在搜索self作为类函数时遇到了这个问题(和答案),看起来像这样:Int.selfString.selfYourClass.self

以前,据我所知,只有德米特里·帕夫鲁汀(Dmitri Pavlutin)的回答触及了这一点,

  

在类型方法(静态函数或类函数)中访问self时,它指的是实际类型(而不是实例)。

以这种方式使用self时,它实际上返回Swift中称为元类型的内容。您可以在此处阅读有关此文档的文档:https://docs.swift.org/swift-book/ReferenceManual/Types.html#//apple_ref/swift/grammar/metatype-type

在swiftrocks.com上使用元类型也非常不错article with examples