Object type evaluation in Swift

I have the following code in Swift:

 func foo()
    {
        let name = "Hello World"

        if name is String
        {

        }
        else
        {

        }
    }


I get the error: 'is' test is always true 

      

I know this is always the case! But why is this a mistake?

+3


source to share


3 answers


This is a mistake because Swift tries his best to keep you in useless things. Swift shows that since this test is always correct, you must have intended to do something else.



+3


source


Swift compiles your declaration through type inference like this:

let name: String = "Hello World"
if name is String { ...

      

You cannot check the type of a variable against a type that has been declared like this, because it will ALWAYS be true, and this is obvious at compile time. In this case, you know exactly what it name

is String

. Swift's static typing means you never have to run this test. You can always assume that the type variable String

is String

.

To use is

var must be hidden, but not identical to the type you are comparing it to. So it will compile if it name

is an ambiguous type, which could String

or could be something else entirely. Then the test really makes sense.



let name: AnyObject = "Hello World"
if name is String {
  println("name is a string")
} else {
  println("name is NOT a string :(")
}

      


Here are some more examples of when you can is

and when you cannot.

// Good
// AnyObject can be casted to String
let name: AnyObject = "Hello World"
if name is String {}

// Also good
// UInt32 can be casted to Int
let num: UInt32 = 123
if num is Int {}

// error: 'String' is not a subtype of 'Int'
// Int cannot be casted to String, this will NEVER be true
let name: Int = 123
if name is String {}

// error: 'is' test is always true
// String will always be string, this will ALWAYS be true
let name: String = "Hello"
if name is String {}

      

+4


source


Variables in swift are (very) strongly typed. If you write something like this, chances are you are doing something wrong in your code.

I understand that the compiler is outputting this as an error - otherwise I might that the else branch might be executed under some conditions.

Data types and structures do not support inheritance, so if you declare a variable String

it cannot be anything else (other than Any

and AnyObject

, which are protocols, though).

If you are declaring a string variable:

var test: String = "test"

      

it can never be anything else, so this always fails:

if test is Int { // < 'Int' is not a subtype of 'String'
    ...
}

      

Testing if the string is a string is pointless, so the compiler considers it an error, although it might be more of a warning, because the code is syntactically and semantically correct.

By the way, checking the data type or structure for Any

and AnyObject

results in the same error, so I assume the same is true for whatever protocol it uses.

+1


source







All Articles