Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift how to "pass by value" of a object

Tags:

ios

swift

I am quite new in Swift. And I create a class(for example):

class Fraction{
    var a: Int
    init(a:Int){
        self.a = a
    } 
    func toString() -> String{
        return "\(self.a)"
    }
}

and I also build a in other class function:

class func A_plusplus(f:Fraction){
    f.a++
}

Then in the executive class I write:

var object = Fraction(a:10)
print("before run func = " + object.toString())
XXXclass.A_plusplus(object)
print("after ran func =" + object.toString() )

So the console output is

before run func = 10; after ran func =11

The question is how can I just send a copy of the "object" to keep its value which equal to 10

And if functions are always pass-by-reference, why we still need the keyword: "inout"

what does difference between A_plusplus(&object)//[if I make the parameter to be a inout parameter] and A_plusplus(object)

Universally, I don't want to use struct. Although this will solve my problem exactly, I do pass-by-value rarely.So I don't want program's copying processes slow my user's phone down :(

And It seems conforming the NSCopying protocol is a good option.But I don't know how to implement the function: func copyWithZone(zone: NSZone)-> AnyObject? correctly

like image 533
Microos Avatar asked Jan 07 '23 08:01

Microos


2 Answers

If your class is subclass of NSObject,better to use NSCopying

class Fraction:NSObject,NSCopying{
var a:Int
var b:NSString?
required init(a:Int){
    self.a = a
}
func toString() -> String{
    return "\(self.a)"
}
func copyWithZone(zone: NSZone) -> AnyObject {
    let theCopy=self.dynamicType.init(a: self.a)
    theCopy.b = self.b?.copy() as? NSString
    return theCopy
}
}
class XXXclass{
class func A_plusplus(f:Fraction){
    f.a++
    f.b = "after"
}

}

var object = Fraction(a:10)
object.b = "before"
print("before run func = " + object.toString())
print(object.b!) //“Before”

XXXclass.A_plusplus(object.copy() as! Fraction)
print("after ran func =" + object.toString() )
print(object.b!)//“Before”

If it is just a common swift class,You have to create a copy method

class Fraction{
var a: Int
init(a:Int){
    self.a = a
}
func toString() -> String{
    return "\(self.a)"
}
func copy()->Fraction{
    return Fraction(a: self.a)
}
}
class XXXclass{
    class func A_plusplus(f:Fraction){
        f.a++
   }
}
var object = Fraction(a:10)
print("before run func = " + object.toString())
XXXclass.A_plusplus(object.copy())
print("after ran func =" + object.toString() )

To make it clear,you have to know that there are mainly two types in swift

  1. Reference types. Like Class instance,function type
  2. Value types,Like struct and others(Not class instance or function type)

If you pass in a Reference types,you pass in the copy of Reference,it still point to the original object.

If you pass in a Copy type,you pass in the copy of value,so it has nothing to do with the original value

Let us talk about inout,if you use it,it pass in the same object or value.It has effect on Value type

func add(inout input:Int){
    input++
}

var a = 10
print(a)//10
add(&a)
print(a)//11
like image 161
Leo Avatar answered Jan 20 '23 21:01

Leo


Swift has a new concept so called "struct"

You can define Fraction as struct (Not class)

And

struct Fraction{
   ...
}
var object = Fraction(a:10)
var object1 = object  //then struct in swift is value type, so object1 is copy of object (not reference)

And if you use struct then try to use inout in A_plusplus function Hope this will help you.

like image 24
Alex Avatar answered Jan 20 '23 19:01

Alex