2016-11-07 27 views
1

我來自Javascript背景,我正在尋找一些清晰的Swift inout。學習Swift - inout函數 - 爲什麼他們修改全局變量值?

在Javascript中,函數的參數只存在於該函數的範圍內。例如,我可以做到這一點沒有問題。

function greet(name) { 
name = "randomDude"; 
return name 
} 

greet("Barry"); 

這是可行的,因爲參數名只存在於問候函數的範圍內。所以我可以改變名字的價值。

然而,斯威夫特,我不能做到這一點:

func greet(name: String) { 
    name = "Ardvark" 
    print(name) 
} 

greet(name: "Drew") 

的解決辦法是將其更改爲「INOUT」功能,只能採取一個變量,即:

func greet(name: inout String) { 
     name = "Ardvark" 
     print(name) 
    } 

var name = "Drew"  
greet(name: name) 

但是,當我這樣做時,它實際上會更改var name的值。這意味着inout函數不會修改函數範圍內的PARAMETER的值,但會修改全局變量。

這是我必須接受的嗎?是否有理由修改全局變量?你將如何修改函數greet中的變量'name'?

由於

+0

我不太明白你的意思。在第二個代碼示例中,變量「name」也僅存在於問候函數的範圍內。爲什麼這不起作用?你不能修改參數,因爲它們默認是常量,但你爲什麼想要? –

+0

@Lupinity參數在Swift 3中是不可變的。你不能在函數內賦給'name'一個新的值。 – rmaddy

+1

@rmaddy:是的,但我沒有看到在那裏分配一個值的意義? –

回答

5

的原因的代碼的第二塊(第一夫特例如)防止你改變name值是因爲在夫特3中,所有的參數是常數。換句話說,它們基本上都是用let來聲明的。

想象你的第一斯威夫特例如爲:

func greet(let name: String) { 
    name = "Ardvark" 
    print(name) 
} 

顯然,你不會真的把let那裏,但是這將有助於你記住,參數是不可改變的。這可以防止您錯誤地更改該值。如果你想改變它只是在函數內部,使用一個新的變量:

func greet(name: String) { 
    let anotherName = "Ardvark" 
    print(anotherName) 
} 

使用inout改變由「去掉讓利」,並允許您更改調用函數時使用的原始變量的參數。

如何修改函數greet中的變量'name'?

你不在Swift 3中。該參數是不可變的。將其分配給函數內的新變量。

+1

也不'inout'意味着所做的修改反映回呼叫環境?這似乎是一個極端的解決方案,不可修改參數的問題... – Pointy

+0

@Pointy是的,這就是爲什麼我在我的最後一行說'inout'可以讓你改變原來的值。通過原始值我的意思是傳遞給函數的變量。 – rmaddy

+0

正確,但我的意思是因爲'inout'意味着它在編程語言中總是意味着什麼,如果你想要做的只是將一個變量初始化爲一個參數的值,那麼你可能會聲明一個'var'變量並初始化它。 (請注意,我不是Swift程序員:) – Pointy

2

func greet(name: String) {}功能name是一個常量,實際上它看起來像func greet(let name: String) {}所以你不能修改它。讓我們添加一個新的變量,併爲其分配的name價值給它:

func greet(name: String) { 
    var newName = name 
    newName = "Ardvark" 
    print(newName) 
} 
0

剛看了一些斯威夫特文檔的。得出兩個結論。

(1)默認情況下,Swift中的參數是CONSTANTS,所以就好像在參數前面有一個let關鍵字。意思是在函數內部,參數值不能改變,否則會拋出錯誤。 (2)將你的函數改成'inout'函數改變了事情。首先,它刪除了'let'約束。其次,當你將參數傳遞給inout參數時,它被稱爲copy-in,copy-out。參數的值被複制到內存中,通過函數傳遞,在函數中被修改,並且新值被分配給作爲參數傳遞的原始變量。

如果您仔細考慮,這些是兩種不同類型的功能。換句話說,沒有像Javascript這樣的功能,只需在函數的作用域內修改參數值即可。

因爲:

的參數是恆定的(默認),

OR ...

您使用的INOUT功能,在這種情況下,該參數是一個變量作爲與常量相反,但該參數僅用於將參數的原始值「轉移」到可修改的函數中,然後作爲新值返回到內存中的原始變量佔位符。

換句話說...... Swift中沒有辦法(我知道)只修改一個參數的值INSIDE的作用範圍。由於參數是一個常量,或者您正在使用inout函數,它不會修改函數內部的參數值,所以默認情況下禁止這樣做......它正在修改GLOBAL名稱空間的值。

相關問題