https://docs.swift.org/swift-book/LanguageGuide/Functions.html
In-Out Parameters
Function parameters are constants by default.
Swiftの関数のパラメータはデフォルトでは定数(letで宣言されているのと同じ)である。
//Swift //↓arguementLabelとparameterNameを使うパターン。2つの使い分けがごっちゃになりやすいが、 //呼び出し時に使うのがargumentLabel、関数定義内(ボディ内)で使うのがparameterName。 //argumentLabelが1番目、parameterNameが2番目、型指定が3番目。これでワンセット。 /* func someFunction(al1 pn1: Int,al2 pn2:Int) { // In the function body, parameterName refers to the argument value // for that parameter. //print(parameterName) print(pn1*pn2) } someFunction(al1:4,al2:9 )//36
(1)ということでSwiftでは関数ボディ内でパラメータaに代入しようとするとコンパイルエラーが発生する。↓
//Swift func someFunc(a:Int){ a=100 //エラー、Cannot assign to value: 'a' is a 'let' constant print(a) } someFunc(a:10)
(2)Dartの場合下記のコードでエラーは出ない。
//Dart void someFunc(int a){ a=100; print(a); } void main(){ someFunc(10);//100 }
(3)ただSwiftでもアーギュメントにclassインスタンスを渡してボディ内でフィールドに値を代入してもエラーは発生しない。Swiftのclassは参照型なので、アーギュメントとしてsomeFuncForClsに渡したsomCls1のfieldの値も3に変わっている。
//Swift class SomeCls{ var field:Int=0 } func someFuncForCls(_ a:SomeCls){ a.field=3 print(a.field) } var someCls1:SomeCls=SomeCls() someFuncForCls(someCls1) //3 print(someCls1.field) //3
(4)その点はDartも同じ。
//Dart class SomeCls{ int field=0; } void someFuncForCls(SomeCls sc){ sc.field=200; print(sc.field); } void main(){ SomeCls sc1=SomeCls(); someFuncForCls(sc1); //200 print(sc1.field); //200 }
(5)SwiftのStruct(構造体)の場合↓。構造体は値型なので、
letで宣言した変数、
あるいは
letで宣言した変数と同じ、関数のパラメータ
のフィールドに代入しようとするとコンパイルエラーとなる。
//Swift struct SomeStruct{ var field:Int=200 } func someFuncForStruct(_ b:SomeStruct){ b.field=5 //←コンパイルエラー、Cannot assign to property: 'b' is a 'let' constant print(b.field) }
(3)においてSomeClsのフィールドfieldをletで宣言すれば、someFuncForCls関数内でフィールドへの代入ができなくなる。イミュータブル ということ。
//Swift class SomeCls{ let field:Int=0 //←letで宣言している。 } func someFuncForCls(_ a:SomeCls){ a.field=3 //←コンパイルエラー、Cannot assign to property: 'field' is a 'let' constant print(a.field) }
(4)において、SomeClsのフィールドfieldをfinalで宣言すれば、someFuncForCls関数のパラメータのフィールドをし変更できなくなる。イミュータブル 。
なのでアーギュメントとして渡したsc1のfieldが意図せず変更される可能性も無くなる。
//Dart class SomeCls { final int field = 0; } void someFuncForCls(SomeCls sc) { sc.field = 200; //←コンパイルエラー、'field' can't be used as a setter because it's final. print(sc.field); } void main() { SomeCls sc1 = SomeCls(); someFuncForCls(sc1); print(sc1.field); }
解説としては
https://qiita.com/koher/items/bcdbf6578b6edd1f9e0c
の解説がわかりやすい。