As per title, ran this across various languages. Results are mixed, but IMHO, it seems unsafe to design your functions/methods this way. It would be better to pass in the object, compute the changes without modifying the object, return the computed changes and assign it back to the original variable.
Below are sample code snippets for each tried language with the output commented at the end of the sample code. Arguments are passed to the function as-is, without using *
pointers or &
addresses (which would hint that the original variable might be modified).
Languages tried (in alphabetical order of file extension): C, C++, Java, Javascript, PHP, Python, Swift. And oh, this little exercise started off when I was looking at some Javascript code 😛
C
Ans: No
/** * test.c * * To run: * gcc test.c -o a.out * ./a.out */ #include <stdio.h> struct MyClass { int myProperty; }; void modifyPrimitive(int myPrimitive) { myPrimitive = 2; printf("myPrimitive: %d\n", myPrimitive); } void modifyObject(struct MyClass myObject) { myObject.myProperty = 2; printf("myObject.myProperty: %d\n", myObject.myProperty); } int main() { int actualPrimitive = 1; printf("actualPrimitive: %d\n", actualPrimitive); modifyPrimitive(actualPrimitive); printf("actualPrimitive: %d\n", actualPrimitive); printf("\n"); struct MyClass actualObject; actualObject.myProperty = 1; printf("actualObject.myProperty: %d\n", actualObject.myProperty); modifyObject(actualObject); printf("actualObject.myProperty: %d\n", actualObject.myProperty); return 0; } /* Output: actualPrimitive: 1 myPrimitive: 2 actualPrimitive: 1 actualObject.myProperty: 1 myObject.myProperty: 2 actualObject.myProperty: 1 */
C++
Ans: No
/** * test.cpp * * To run: * gcc test.cpp -o a.out * ./a.out */ #include <stdio.h> class MyClass { public: int myProperty; }; void modifyPrimitive(int myPrimitive) { myPrimitive = 2; printf("myPrimitive: %d\n", myPrimitive); } void modifyObject(MyClass myObject) { myObject.myProperty = 2; printf("myObject.myProperty: %d\n", myObject.myProperty); } int main() { int actualPrimitive = 1; printf("actualPrimitive: %d\n", actualPrimitive); modifyPrimitive(actualPrimitive); printf("actualPrimitive: %d\n", actualPrimitive); printf("\n"); MyClass actualObject; actualObject.myProperty = 1; printf("actualObject.myProperty: %d\n", actualObject.myProperty); modifyObject(actualObject); printf("actualObject.myProperty: %d\n", actualObject.myProperty); return 0; } /* Output: actualPrimitive: 1 myPrimitive: 2 actualPrimitive: 1 actualObject.myProperty: 1 myObject.myProperty: 2 actualObject.myProperty: 1 */
Java
Ans: Yes
/** * test.java * * To run: * javac test.java * java main */ import java.io.*; class MyClass { public int myProperty; } class main { public static void main(String[] args) throws Exception { int actualPrimitive = 1; System.out.printf("actualPrimitive: %d\n", actualPrimitive); modifyPrimitive(actualPrimitive); System.out.printf("actualPrimitive: %d\n", actualPrimitive); System.out.printf("\n"); MyClass actualObject = new MyClass(); actualObject.myProperty = 1; System.out.printf("actualObject.myProperty: %d\n", actualObject.myProperty); modifyObject(actualObject); System.out.printf("actualObject.myProperty: %d\n", actualObject.myProperty); } public static void modifyPrimitive(int myPrimitive) { myPrimitive = 2; System.out.printf("myPrimitive: %d\n", myPrimitive); } public static void modifyObject(MyClass myObject) { myObject.myProperty = 2; System.out.printf("myObject.myProperty: %d\n", myObject.myProperty); } } /* Output: actualPrimitive: 1 myPrimitive: 2 actualPrimitive: 1 actualObject.myProperty: 1 myObject.myProperty: 2 actualObject.myProperty: 2 */
Javascript
Ans: Yes
/** * test.js * * To run: * node test.js */ function modifyPrimitive(myPrimitive) { myPrimitive = 2; console.log("myPrimitive: ", myPrimitive); } function modifyObject(myObject) { myObject.myProperty = 2; console.log("myObject.myProperty: ", myObject.myProperty); } var actualPrimitive = 1; console.log("actualPrimitive: ", actualPrimitive); modifyPrimitive(actualPrimitive); console.log("actualPrimitive: ", actualPrimitive); console.log(""); var actualObject = { myProperty: 1 }; console.log("actualObject.myProperty: ", actualObject.myProperty); modifyObject(actualObject); console.log("actualObject.myProperty: ", actualObject.myProperty); /* Output: actualPrimitive: 1 myPrimitive: 2 actualPrimitive: 1 actualObject.myProperty: 1 myObject.myProperty: 2 actualObject.myProperty: 2 */
PHP
Ans: Yes
<?php /** * test.php * * To run: * php test.php */ class MyClass { public $myProperty; } function modifyPrimitive($myPrimitive) { $myPrimitive = 2; printf("myPrimitive: %d\n", $myPrimitive); } function modifyObject(MyClass $myObject) { $myObject->myProperty = 2; printf("myObject.myProperty: %d\n", $myObject->myProperty); } $actualPrimitive = 1; printf("actualPrimitive: %d\n", $actualPrimitive); modifyPrimitive($actualPrimitive); printf("actualPrimitive: %d\n", $actualPrimitive); printf("\n"); $actualObject = new MyClass(); $actualObject->myProperty = 1; printf("actualObject.myProperty: %d\n", $actualObject->myProperty); modifyObject($actualObject); printf("actualObject.myProperty: %d\n", $actualObject->myProperty); /* Output: actualPrimitive: 1 myPrimitive: 2 actualPrimitive: 1 actualObject.myProperty: 1 myObject.myProperty: 2 actualObject.myProperty: 2 */
Python
Ans: Yes
""" test.py To run: python test.py python3 test.py """ class MyClass: myProperty = 0 def modifyPrimitive(myPrimitive): myPrimitive = 2 print("myPrimitive: {}".format(myPrimitive)) def modifyObject(myObject): myObject.myProperty = 2 print("myObject.myProperty: {}".format(myObject.myProperty)) actualPrimitive = 1 print("actualPrimitive: {}".format(actualPrimitive)) modifyPrimitive(actualPrimitive) print("actualPrimitive: {}".format(actualPrimitive)) print("") actualObject = MyClass() actualObject.myProperty = 1 print("actualObject.myProperty: {}".format(actualObject.myProperty)) modifyObject(actualObject) print("actualObject.myProperty: {}".format(actualObject.myProperty)) """ Output (both Python 2 & Python 3): actualPrimitive: 1 myPrimitive: 2 actualPrimitive: 1 actualObject.myProperty: 1 myObject.myProperty: 2 actualObject.myProperty: 2 """
Swift
Ans: Yes
/** * test.swift * * To run: * swift test.swift */ class MyClass { public var myProperty: Int = 0 } func modifyPrimitive(_ myPrimitive: Int) { var myPrimitive = myPrimitive // needed else "error: cannot assign to value: 'myPrimitive' is a 'let' constant" myPrimitive = 2 print("myPrimitive: \(myPrimitive)") } func modifyObject(_ myObject: MyClass) { myObject.myProperty = 2 print("myObject.myProperty: \(myObject.myProperty)") } var actualPrimitive: Int = 1 print("actualPrimitive: \(actualPrimitive)") modifyPrimitive(actualPrimitive) print("actualPrimitive: \(actualPrimitive)") print("") var actualObject: MyClass = MyClass() actualObject.myProperty = 1 print("actualObject.myProperty: \(actualObject.myProperty)") modifyObject(actualObject) print("actualObject.myProperty: \(actualObject.myProperty)") /* Output: actualPrimitive: 1 myPrimitive: 2 actualPrimitive: 1 actualObject.myProperty: 1 myObject.myProperty: 2 actualObject.myProperty: 2 */