8

I know what inout does for value types.

With objects or any other reference type, is there a purpose for that keyword in that case, instead of using var?

Code example:

private class MyClass {
    private var testInt = 1
}

private func testParameterObject(var testClass: MyClass) {
    testClass.testInt++
}

private var testClass: MyClass = MyClass()
testParameterObject(testClass)
testClass.testInt // output ~> 2

private func testInoutParameterObject(inout testClass: MyClass) {
    testClass.testInt++
}

testClass.testInt = 1
testInoutParameterObject(&testClass) // what happens here?
testClass.testInt // output ~> 2

It could be the same as simply the var keyword in the parameter list.

Community
  • 1
  • 1
Binarian
  • 12,296
  • 8
  • 53
  • 84

2 Answers2

11

The difference is that when you pass a by-reference parameter as a var, you are free to change everything that can be changed inside the passed object, but you have no way of changing the object for an entirely different one.

Here is a code example illustrating this:

class MyClass {
    private var testInt : Int
    init(x : Int) {
        testInt = x
    }
}

func testInoutParameterObject(inout testClass: MyClass) {
    testClass = MyClass(x:123)
}

var testClass = MyClass(x:321)
println(testClass.testInt)
testInoutParameterObject(&testClass)
println(testClass.testInt)

Here, the code inside testInoutParameterObject sets an entirely new MyClass object into the testClass variable that is passed to it. In Objective-C terms this loosely corresponds to passing a pointer to a pointer (two asterisks) vs. passing a pointer (one asterisk).

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thanks, it is a bit tricky, since there is no warning that setting the `var` parameter to a new object does simply nothing. I just oversaw that. It is the same for all reference types then? – Binarian Feb 01 '15 at 14:48
  • 2
    @ViktorLexington Yes, this is the same for reference types. Strictly speaking, setting a plain `var` does something - it changes the object for the duration of the function, in the same way that a pass-by-value in Objective-C would let you change parameters without making changes in the caller's context. – Sergey Kalinichenko Feb 01 '15 at 14:53
  • 2
    @dasblinkenlight tiny follow up question, in addition to the above (where inout lets you literally replace the object instance referred to by the parameter), am I correct in my assumption that if I pass a reference type (object) in swift as a *standard* parameter type (no inout and no var), that IF a property of the object is modified by a function it was passed to, then that change will exist outside the scope of the function? i.e. changes to ref types inside functions are seen outside functions (even without var/inout). correct? – Woodstock Oct 01 '15 at 21:34
  • 2
    @Woodstock Yes. If you modify the _properties_ of a passed-in object inside a function, those changes will be visible outside the function's scope. This is a very common pattern; the `inout` keyword should _only_ be used when the function modifies the variable itself (i.e., replaces the object it refers to with another one). – Nolan Amy Sep 05 '18 at 17:05
4

It does the exact same thing for all types. Without inout, it is pass-by-value (regardless of type). That means assigning (=) to the parameter inside the function has no effect on the calling scope. With inout, it is pass-by-reference (regardless of type). That means assigning (=) to the parameter inside the function has the same effect as assigning to the passed variable in the calling scope.

newacct
  • 119,665
  • 29
  • 163
  • 224
  • 2
    @ViktorLexington: Isn't that exactly what I said? Please be specific about whether you agree with my answer or not, and if not, which part you do not agree with. – newacct Feb 02 '15 at 18:45
  • The question was, if there is a difference with both of the keywords, var and inout FOR REFERENCE TYPES are pass by reference. It is always pass by reference. Passing a reference as value is also pass by reference. – Binarian Feb 04 '15 at 18:18
  • The accepted answer showed me the difference between pass by reference and pass by double reference like often used by nserror in objective c – Binarian Feb 04 '15 at 18:42
  • 3
    @ViktorLexington: "Passing a reference as value is also pass by reference." ABSOLUTELY NOT. That is Pass-by-Value. Without `inout` is always pass-by-value. With `inout` is always pass-by-reference. This is true regardless of value type or reference type. – newacct Feb 04 '15 at 19:29
  • an object is a refetence type, pass it without inout, and you are passing the object (like inout with value types), which is effectivly pass by reference, try it out. Changing the value of that object also changes the orginal object (without inout)! Did you even read my question with the code? – Binarian Feb 04 '15 at 20:38
  • 2
    @ViktorLexington: You cannot "pass an object" because objects are not values in Swift. You can have references to objects which are values. If we don't have `inout` and `&`, passing and assigning in Swift is semantically identical to that in Java (which also has value types and reference types). Look anywhere on StackOverflow or the Internet and Java is always described as pass-by-value only. – newacct Feb 04 '15 at 23:56
  • 3
    @ViktorLexington: The question is "Does inout parameter make any difference with reference type?" The answer is, there is a difference and it is *the exact same difference* as with value types, which is: pass-by-value vs. pass-by-reference. There is no difference between types. How is that not a right answer to the question? – newacct Feb 05 '15 at 20:10
  • 1
    The question states clearly it is only about reference types. Even if it does technically behave the same like value types, it is semantically different, a var parameter with a reference type does copy the address but it is pass by reference. The question was, what can I do with inout reference type parameter more - answer is: set the reference to another object. – Binarian Feb 07 '15 at 18:39
  • 2
    @ViktorLexington: "it is semantically different" It is *semantically* identical. "but it is pass by reference" Again, it is PASS-BY-VALUE. It is *semantically* identical to Java, which is pass-by-value only. – newacct Feb 07 '15 at 20:30
  • 1
    I am sorry. I looked up different websites before and all defined pass by reference wrong! What I meant was: When I already have a pointer to something and I am copying the pointer, the parameter isn't the value, it is the pointer. I did understand that you meant passing the value of the address of the object, but thought pass by reference only means having a pointer to an object. I should research better next time. (Apple should have called it pointer type, reference type is misleading that reference is for parameters) – Binarian Feb 13 '15 at 07:28