Swift is a type safe language. A type-safe language gives you a clear idea of the type of value the code will handle. If your code needs one String , you can never accidentally pass in one Int .
Because Swift is type-safe, it does type checking when compiling your code (type checks) and marks the mismatched type as an error. This allows you to find and fix bugs early in the development.
When you are dealing with different types of values, type checking can help you avoid errors. However, this does not mean that you need to explicitly specify the type each time you declare constants and variables. If you do not explicitly specify a type, Swift uses type inference (inference) to select the appropriate type. With type inference, the compiler can automatically infer the type of an expression when compiling code. The principle is simple, just check your assigned value.
Because of the type inference, Swift rarely needs to declare a type than C or objective-c. Constants and variables require explicit typing, but most work does not need to be done by yourself.
Type inference is useful when you declare constants or variables and assign initial values. You can trigger type inference when you declare constants or variables by assigning them a literal (literal value or literal). (The literal is the value that will appear directly in your code, such as 42 and 3.14159 .) )
For example, if you assign a value to a new constant 42 and do not indicate a type, Swift can infer that the constant type is Int , because the initial value you assign to it looks like an integer:
let meaningOfLife = 42// meaningOfLife 会被推测为 Int 类型
Similarly, if you do not specify a type for floating-point literals, Swift will infer that you want to Double :
let pi = 3.14159// pi 会被推测为 Double 类型
When you infer the type of a floating-point number, Swift always chooses Double instead Float .
If both integers and floating-point numbers appear in the expression, they are inferred as Double types:
let anotherPi = 3 + 0.14159// anotherPi 会被推测为 Double 类型
The original value 3 does not explicitly declare a type, and a floating-point literal appears in the expression, so the expression is inferred as a Double type.
Numeric type literal
The integer number of polygons can be written:
- A decimal number with no prefix
- A binary number, prefixed by
0b
- An octal number, prefixed by
0o
- A hexadecimal number, prefixed by
0x
The decimal values for all of the following integer literals are 17 :
let decimalInteger = 17let binaryInteger = 0b10001 // 二进制的17let octalInteger = 0o21 // 八进制的17let hexadecimalInteger = 0x11 // 十六进制的17
Floating-point literals can be either decimal (without a prefix) or hexadecimal (prefixed 0x ). There must be at least one decimal digit (or hexadecimal number) on either side of the decimal point. Floating-point literals also have an optional exponent (exponent, specified in a decimal floating-point number in uppercase or lowercase e , in hexadecimal floating-point numbers, in uppercase or lowercase p .
If the exponent of a decimal number is exp , that number is equal to the product of cardinality and 10^exp:
1.25e2Represents 1.25x10^2, equals 125.0 .
1.25e-2Represents 1.25x10^-2, equals 0.0125 .
If the exponent of a hexadecimal number is exp , that number is equal to the product of cardinality and 2^exp:
0xFp2Represents 15x2^2, equals 60.0 .
0xFp-2Represents 15x2^-2, equals 3.75 .
The following floating-point literals are equal to the decimal number 12.1875 :
let decimalDouble = 12.1875let exponentDouble = 1.21875e1let hexadecimalDouble = 0xC.3p0
Numeric class literals can include additional formatting to enhance readability. Both integers and floating-point numbers can be added with an additional 0 and underlined, without affecting the literal:
let paddedDouble = 000123.456let oneMillion = 1_000_000let justOverOneMillion = 1_000_000.000_000_1
Numeric type conversions
In general, use a type even if the integer constants and variables in your code are known to be non-negative Int . Always use the default integer type to ensure that your integer constants and variables can be reused directly and can match the type inference of the integer class literal.
Use other integer types only when necessary, such as to handle externally-defined data or to optimize performance, memory consumption, and so on. Using a type with an explicit length specifies that a value overflow can be found in time and implies that special data is being processed.
Integer conversions
Variables and constants of different integer types can store numbers of different ranges. A constant or variable of a Int8 type can store a number range of -128 ~ 127 , whereas a UInt8 constant or variable of type can store a number range of 0 ~ 255 . If the number exceeds the range of constants or variables that can be stored, errors are made when compiling:
let cannotBeNegative: UInt8 = -1// UInt8 类型不能存储负数,所以会报错let tooBig: Int8 = Int8.max + 1// Int8 类型不能存储超过最大值的数,所以会报错
Because each integer type can store different ranges of values, you must selectively use numeric type conversions depending on the situation. This selective approach prevents implicit conversion errors and makes the type conversion intent in your code clear.
To convert one number type to another, you use the current value to initialize a new number of the desired type, which is the type of your target. In the following example, a constant twoThousand is a UInt16 type, whereas one a constant is a UInt8 type. They cannot be added directly because they are of different types. So call UInt16(one) to create a new number and UInt16 initialize it with one the value, and then use this new number to calculate:
let twoThousand: UInt16 = 2_000let one: UInt8 = 1let twoThousandAndOne = twoThousand + UInt16(one)
Now the two number types are UInt16 , and can be added. The type of the target constant is twoThousandAndOne inferred as UInt16 it is the UInt16 and of two values.
SomeType(ofInitialValue)Is the default method that invokes the Swift constructor and passes in an initial value. Inside the language, UInt16 there is a constructor that can accept a UInt8 value of a type, so the constructor can UInt8 create a new one with the existing ones UInt16 . Note that you cannot pass in any type of value, only the UInt16 value inside the corresponding constructor is passed in. However, you can extend an existing type to allow it to receive other types of values (including custom types), refer to extensions.
Integer and floating-point conversion
The conversion of integers and floating-point numbers must explicitly specify the type:
let three = 3let pointOneFourOneFiveNine = 0.14159let pi = Double(three) + pointOneFourOneFiveNine// pi 等于 3.14159,所以被推测为 Double 类型
In this example, the three value of a constant is used to create a Double value of type, so the number on both sides of the plus sign must be the same. If you do not convert, both cannot be added.
The inverse conversion of a floating-point number to an integer is the same line, and the integer type can be Double initialized with or Float type:
let integerPi = Int(pi)// integerPi 等于 3,所以被推测为 Int 类型
When a new integer value is initialized in this way, the floating-point value is truncated. In other words 4.75 , it will become 4 , -3.9 will become -3 .
Attention:
The combination of a numeric class constant and a variable differs from the combination of a numeric class literal. Literals 3 can be added directly and literally 0.14159 , because the number literal itself has no definite type. Their type is only inferred when the compiler requires a value.
Type aliases
Type aliases is the definition of another name for an existing type. You can use typealias keywords to define type aliases.
Type aliases are useful when you want to give a more meaningful name to an existing type. Suppose you are working with data for a specific length of external resource:
typealias AudioSample = UInt16
Once you have defined a type alias, you can use the alias anywhere you use the original name:
var maxAmplitudeFound = AudioSample.min// maxAmplitudeFound 现在是 0
In this case, it AudioSample is defined as UInt16 an alias. Because it is an alias, it AudioSample.min is actually UInt16.min , so it will give maxAmplitudeFound an initial value 0 .
Type safety and type inference