I have always preferred explicitly typed languages, saving a couple of characters by simply declaring a variable as var or let can quickly end up in a game of “Guess who?” or “what” to be more precise.
Its straight forward enough with immediate assignments or when the expected type is clear.
1 2 3 |
var name = "Foo" //clearly String var street = customer.street //most likely String var customer = Customer(name: "Foo", ...) |
However when dealing with complex domain models or business functions with unclear return type the value of strong typing quickly becomes apparent.
1 2 3 |
var value = contract.amount //Int/UInt/Float/Double/String/...? var customer = contract.customer //String/domain model Customer/...? var amountDue = billingService.calculate(...) //Int/UInt/Float/Double/...? |
Swift is still a statically typed language, it employees type inference to define the type of variables and constants. Hence once a type has been inferred, the variable cannot be reused later on for a different type.
1 2 3 4 5 6 |
var foo = "foo" foo = true //compiler error ERROR at line 58, col 7: cannot assign value of type 'Bool' to type 'String' foo = true ^~~~ |
This is very similar to what has been proposed in JEP 286: Local-Variable Type Inference for Java 9. Citing complaints about unnecessary boilerplate code as a core reason.
Swift also allows “type annotation” of variables and constants. Having worked with Java for so many years, I feel far more comfortable when the types are defined explicitly, giving that extra bit of contextual information.
1 2 3 |
var value: Int = contract.amount //Int var customer: Customer = contract.customer //Customer type var result: Double? = billingService.calculate(...) //returns an optional Double |
In Swift constants are defined with let. The value of the constant does not have to be known at compile time, but may not be changed after assignment.
1 2 |
let answer: Int = 42 answer = 42 + 8 //results in compilation error |
This is equivalent to final in Java. This is one point where the verbosity of Java becomes a disadvantage. Consider the code example below, using constants with final makes the code clearer and allows for compile time checking.
1 2 3 4 5 6 7 8 |
private final String id; public void foo(final String bar) { final String barCap = bar.toUpperCase(); String output = "FOO"; output += barCap; ... } |
Yet most of the time the final key word is omitted, I am as guilty of this as anyone else.
When comparing the same code in Swift the first thing you notice is that the parameter doesn’t have a modifier. Unlike Java parameters are constant by default.
1 2 3 4 5 6 |
func foo(bar: String) { let barLC = bar.uppercased() //without type annotation var output = "FOO" output += barLC ... } |
It is much more common to find constants in Swift code then in Java code, its quite surprising that a couple of characters can lead to an entirely different coding style.
This was a quick look at Swift variable, constants and Type Inference, the next post will have a look at Swifts data types from classes, structures, tuples to enums.
Further Resources:
JEP 286: Local-Variable Type Inference (Java 9 Proposal)
Types and Type Inference (SWIFT)
Swift – The Basics