iOS development Language Swift entry---classes and structs

Source: Internet
Author: User
Tags shallow copy

iOS development language Swift Getting started serial-classes and structs

Classes and structs are a common and flexible construct that people use to build code. In order to implement various functions in classes and structs, we must define attributes and add methods in strict accordance with the syntax rules specified by constants, variables, and functions.
Unlike other programming languages, Swift does not require you to create separate interfaces and implementation files for your custom classes and structs. All you have to do is define a class or struct in a single file, and the system will automatically generate external interfaces for other code.
Attention:
Typically an instance of a class is called an object. However, in swift, classes and structs are more closely related than in other languages, and most of the features discussed in this chapter can be used on classes and structs. Therefore, we will primarily use instances rather than objects.
  

Class and struct comparison

Classes and structs in Swift have a lot in common. The Common place is:
Defining properties for storing values
Define methods to provide functionality
Defining satellite scripts for accessing values
Defining constructors for generating initialization values
Extended to add functionality to the default implementation
Compliance with protocols to provide standard functionality for a class
For more information, see Properties, methods, subscript scripts, initial procedures, extensions, and protocols.
Compared to structs, classes have the following additional functions:
Inheritance allows one class to inherit the characteristics of another class
Type conversions allow you to check and interpret the type of a class instance at run time
The destructor allows an instance of a class to release any resources it has been assigned
Reference count allows multiple references to a class
For more information, see Inheritance, type conversions, initialization, and automatic reference counting.
Attention:
The struct is passed in the code in a copied way, so do not use reference counting.
  

Defined

Classes and structs are defined in a similar way. We represent classes and structs by keyword class and struct, and define their specific contents in a pair of braces:

class SomeClass {    // class definition goes here}struct SomeStructure {    // structure definition goes here}

Attention:
Each time you define a new class or struct, you actually define a new Swift type effectively. So use uppercamelcase this way to name (such as SomeClass and somestructure, etc.) to conform to the uppercase naming style of the standard swift type (such as String, INT, and BOOL). Instead, use Lowercamelcase to name properties and methods (such as framerate and incrementcount) so that they are distinguished from the class.
The following is an example of defining a struct and defining a class:

struct  Resolution {var  width = 0  var  Heigth = 0 }class  Span class= "Hljs-title" >videomode  { var  Resolution = Resolution () var  interlaced = false  var  framerate = 0.0   var  name:string}  

In the example above we define a struct named resolution, which describes the pixel resolution of a display. This structure contains two storage properties called width and height. A stored property is a constant or variable that is bundled and stored in a class or struct. When both properties are initialized to integer 0, they are inferred to be of type int.
In the example above, we also defined a class named Videomode that describes a particular pattern for a video display. This class contains four storage attribute variables. The first is the resolution, which is initialized to a new instance of the resolution struct, with the resolution property type. The new Videomode instance also initializes the other three properties, which are interlaced with an initial value of false (meaning "non-interlaced video"), framerate with a playback frame rate of 0.0, and a value of optional string 's name. The Name property is automatically assigned a default value of nil, meaning "No Name value" because it is an optional type.
  

Classes and struct-body instances

The definition of Resolution struct and Videomode class only describes what is Resolution and Videomode. They do not describe a specific resolution (resolution) or video mode. To describe a particular resolution or video pattern, we need to generate an instance of them.
The syntax for generating struct and class instances is very similar:
[Java] Plain text view copy code

let someResolution = Resolution()let someVideoMode = VideoMode()

Both structs and classes use the constructor syntax to generate new instances. The simplest form of constructor syntax is to follow an empty bracket, such as resolution () or Videomode (), after the type name of the struct or class. The properties of the class or struct instance created in this way are initialized to the default values. The construction process chapters discuss the initialization of classes and structs in more detail.
  

Property access

By using dot syntax (dot syntax), you can access the properties contained in the instance. The syntax rule is that the instance name is followed by the property name, both by the dot number (. Connection

ofisofis 0"

In the example above, someresolution.width refers to the width property of someresolution and returns the initial value of width 0.
You can also access the child properties, how to videomode the width property of the resolution property:

ofisofis 0"

You can also assign a value to a property variable using dot syntax:

ofisnowofisnow 1280"

Attention:
Unlike the Objective-c language, Swift allows you to directly set child properties of a struct property. The last example above is to set the Somevideomode property of the resolution property directly, and the above operation does not need to reset the resolution property.
  

struct type member-by-constructor

All structs have an automatically generated member-by-constructor that initializes the properties of members in the new struct instance. The initial values for each property in the new instance can be passed to the member-by-constructor by the name of the property:

let vga = resolution(width:640480)

Unlike structs, class instances do not have a default member-by-constructor. The constructor is discussed in more detail in the Construction process section.
  

Structs and enumerations are value types

A value type is assigned to a variable, and the constant or itself is passed to a function, and the copy is actually manipulated.
In the previous chapters, we have used a lot of value types. In fact, in Swift, all the basic types: integers, floating-point numbers (floating-point), Boolean values (Booleans), strings (string), arrays (array), and dictionaries (dictionaries) are value types , and are implemented in the background in the form of structs.
In Swift, all structs and enumerations are value types. This means that their instances, as well as any value type attributes contained in the instance, are copied when passed in the code.
Take a look at the following example, which uses the resolution struct in the previous example:

let19201080)var cinema = hd

In the example above, a constant named HD is declared with a value of resolution instance initialized to full HD video resolution (1920 pixels wide and 1080 pixels high).
The example then declares a variable named cinema with a value of the previously declared HD. Because resolution is a struct, cinema's value is actually a copy of HD, not HD itself. Although HD and cinema have the same wide (width) and high (height) properties, they are two completely different instances in the background.
Below, in order to meet the demand for digital cinema screenings (2048 pixels wide and 1080 pixels high), cinema's width property needs to be modified as follows:

cinema.width = 2048

Here, you will see that cinema's width property has been changed to 2048:

isnow  isnow 2048 pixels wide"

However, the width attribute in the original HD instance is still 1920:
[Java] Plain text view copy code

println("hd is still \(hd.width    ) pixels wide")// 输出 "hd is still 1920 pixels wide"

When you assign HD to cinema, you actually copy the values stored in HD, and then store the copied data in a new cinema instance. The result is that two completely independent instances happen to contain the same values. Because they are independent of each other, changing the width of cinema to 2048 does not affect the width (width) in HD.
Enumerations also follow the same Code of conduct:

enum CompassPoint {    case North, South, East, West}var currentDirection = CompassPoint.Westlet rememberedDirection = currentDirectioncurrentDirection = .Eastif rememberDirection == .West {    println("The remembered direction is still .West")}// 输出 "The remembered direction is still .West"

In the example above, Remembereddirection is given the value of currentdirection, which is actually given a copy of the value. Modifying the value of the currentdirection after the assignment process ends does not affect the copy of the original value (value) stored by remembereddirection.
  

Class is a reference type

Unlike a value type, a reference type is referenced when assigned to a variable, constant, or passed to a function, and is not a copy. Therefore, the reference is made to the existing instance itself, not to its copy.
Take a look at the following example, which uses the Videomode class that was previously defined:

let tenEighty = VideoMode()tenEighty.resolution = hdtenEighty.interlaced = truetenEighty.name"1080i"tenEighty.frameRate25.0

In the example above, a constant named Teneighty is declared that references a new instance of the Videomode class. In the previous example, this video mode was given a copy (HD) of HD resolution (1920*1080). Also set to interleaved (interlaced), named "1080i". Finally, its frame rate is 25.0 frames per second.
The teneighty is then given a new constant named Alsoteneighty, while modifying the frame rate of the alsoteneighty:

let30.0

Because the class is a reference type, teneight and Alsoteneight actually refer to the same Videomode instance. In other words, they are two kinds of names for the same instance.
Below, by looking at the Framerate property of Teneighty, we find that it correctly shows the new frame rate of the base Videomode instance with a value of 30.0:

ofisnowofisnow 30.0"

It is important to note that Teneighty and Alsoteneighty are declared as constants ((constants) instead of variables. However, you can still change teneighty.framerate and alsoteneighty.framerate, because these two constants do not change themselves. They do not store the Videomode instance, which is simply a reference to the Videomode instance in the background. So, the change is the framerate parameter of the referenced base videomode, without changing the value of the constant.
  

Identity operator

Because a class is a reference type, there may be multiple constants and variables that reference a class instance at the same time in the background. (This is not true for structs and enumerations.) Because they are value types, their values are always copied when assigned to a constant, variable, or passed to a function. )
It would be helpful to be able to determine whether two constants or a variable references the same class instance. In order to achieve this, Swift has built two identity operators:
Equivalent to (= = =)
Unequal to (!==)
These two operators are used to detect two constants or whether a variable refers to the same instance:

if tenEighty === alsoTenTighty {    println("tenTighty and alsoTenEighty refer to the same Resolution instance.")}//输出 "tenEighty and alsoTenEighty refer to the same Resolution instance."

Note that "equivalent to" (denoted by three equals, = = =) differs from "equals" (denoted by two equals, = =):
A constant or variable that is equivalent to a class type representing two classes is referring to the same class instance.
"Equals" means that the value of two instances is "equal" or "same", and it is a more appropriate term to be judged in accordance with the criteria defined by a Class designer definition.
When you define your custom classes and structs, you are obligated to decide on the criteria for determining the "equality" of two instances. The process of implementing custom "equals" and "not equals" operators is described in detail in chapter operator functions (Operator Functions).
Pointer
If you have experience with c,c++ or objective-c language, then you might know that these languages use pointers to refer to addresses in memory. A Swift constant or variable referencing an instance of a reference type is similar to a pointer in C, but not directly to an address in memory, and does not require you to use an asterisk (*) to indicate that you are creating a reference. These references in Swift are defined in the same way as other constants or variables.
 

Selection of classes and structure bodies

In your code, you can use classes and structs to define your custom data types.
However, struct instances are always passed by value, and class instances are always passed by reference. This means that the two apply different tasks. When you consider the construction and function of a project's data, you need to decide whether each data construct is defined as a class or struct.
According to the general guidelines, consider building a struct when one or more of the following conditions are met:
The primary purpose of the struct is to encapsulate a small number of related simple data values.
It is reasonable to expect that when an instance of a struct is assigned or passed, the encapsulated data will be copied instead of referenced.
Any value type attribute stored in the struct will also be copied, not referenced. The
struct does not need to inherit the properties or behavior of another existing type. The
Appropriate structure candidate includes:
the size of the geometry, encapsulating a width property and a height property, both of which are of type double.
A path within a range that encapsulates a start property and a length property, both of which are of type int.
a point within a three-dimensional coordinate system that encapsulates the X, Y, and Z Properties, all of which are double types.
In all other cases, define a class, generate an instance of it, and manage and pass it by reference. In practice, this means that the vast majority of custom data constructs should be classes, not structs. Assignment and copy behavior of the
Collection (Collection) type
The array and dictionary (Dictionary) types in Swift are implemented in the form of structs. However, when an array is assigned a constant or variable, or is passed to a function or method, its copy behavior is slightly different from that of the dictionary and other structures.
The following description of the behavior of the array and struct is different from the behavior description of Nsarray and Nsdictionary, which is implemented in the form of a class, the former is implemented in the form of a struct. Nsarray and Nsdictionary instances are always assigned and passed in a way that references to existing instances, rather than copies.
Note:
The following is a description of the copy of the array, dictionary, string, and other values. In your code, the copy seems to have actually been generated where there is copy behavior. However, in the background of Swift, the actual (actual) copy will be executed only if it is necessary. Swift manages all of the value copies to ensure performance optimization, so there is no need to avoid assigning values to ensure optimal performance. (actual assignment is optimized by System management)

Assignment and copy behavior of dictionary types

Whenever a dictionary instance is assigned to a constant or variable, or is passed to a function or method, the dictionary is copied when the assignment or invocation occurs. This procedure is described in detail in the chapter structure and enumeration as value types.
If the keys and/or values stored in the dictionary instance are value types (struct or enum), they are copied when the assignment or invocation occurs. Conversely, if the keys and/or values are reference types, the copy will be a reference, not a class instance or function referenced by them. The copy behavior of the dictionary's keys and values is the same as the copy behavior of the properties stored by the struct.
The following example defines a dictionary named ages, which stores the names and ages of four people. The ages dictionary is given a new variable named Copiedages, and ages is copied during the assignment. At the end of the assignment, ages and Copiedages become two independent dictionaries.

var ages = ["Peter"23"Wei"35"Anish"65"Katya"19]var copiedAges = ages

The key (keys) of this dictionary is the string type, and the value (values) is the integer (Int) type.  Both types are value types in swift, so when the dictionary is copied, both will be copied. We can prove that the ages dictionary is actually copied by changing the age value in a dictionary to check the value in another dictionary. If you set the value of Peter to 24 in the Copiedages dictionary, the ages dictionary will still return the value 23 before the modification:

copiedAges["Peter"] = 24println(ages["Peter"])// 输出 "23"
Assignment and copy behavior of arrays

In Swift, the assignment and copy behavior of an array (Arrays) type is much more complex than a dictionary (Dictionary) type.  When manipulating the contents of an array, an array can provide performance near the C language, and the copy behavior occurs only when necessary. If you assign an array instance to a variable or constant, or pass it as a parameter to a function or method call, the contents of the array will not be copied when the event occurs. Instead, the array is common with the same sequence of elements.  When you modify an element within an array, the result of the modification is also displayed in the other array. For arrays, copy behavior occurs only if the operation has the potential to modify the length of the array. This behavior includes attaching (appending), inserting (inserting), deleting (removing), or using a range subscript (ranged subscript) to replace the elements in this range. The behavior rules of the array contents are the same as the key values in the dictionary only when the array copy is actually in place, see section [Collection type assignment and copy behavior] (#assignment_and_copy_behavior_for_collection_  Types The following example assigns an array of integers (Int) to a variable named a, which is then assigned to variables B and C:

var a = [123]var b = avar c = a

We can use the next banner method on a, B, C to get the first Z-fruit of the array to modify the value of an element in the array by the following banner, then the corresponding value in a, B, C will change. Note that when you use the following banner to modify a value, there is no copy behavior that accompanies it, because the following table syntax modifies the value without altering the array length possible:

a[0] = 42println(a[0])// 42println(b[0])// 42println(c[0])// 42

However, when you attach a new element to a, the length of the array changes. When an additional element occurs, Swift creates a copy of the array.  Thereafter, a will be a separate copy of the original array. After the copy occurs, if you modify the element value in a again, a will return a different result than B, C, because the two references are the original array:

a.append(4)a[0] = 777println(a[0])// 777println(b[0])// 42println(c[0])// 42

It is important to ensure that the uniqueness of the array is preceded by an array, or passed to the function, and the method call is necessary to make sure that the array has a unique copy. The uniqueness of the array reference is determined by calling the Unshare method on the array variable. (You cannot call the Unshare method when an array is assigned to a constant) if an array is referenced by more than one variable, and the Unshare method is called on one of the variables, the array is copied, and the variable will have its own independent array copy.  When an array is referenced by only one variable, no copy occurs. At the end of the previous example, both B and C refer to the same array. At this point, the Unshare method in B will change B to a single copy:

b.unshare()

After the Unshare method call modifies the value of the first element in B, the three arrays (a, B, c) return a different three values:
[Java] Plain text view copy code

b[0] = -105println(a[0])// 77println(b[0])// -105println(c[0])// 42

Determine whether two arrays share the same element we use the identity operators (= = = and!==) to determine that two arrays or sub-arrays share the same storage space or element. The following example uses the equivalent (identical to) operator (= = =) to determine whether B and C share the same array elements:

if b === c {    println("b and c still share the same array elements."else {    println("b and c now refer to two independent sets of array elements.")}
andnowof array elements."

In addition, we can use the identity operator to determine whether two sub-arrays share the same elements. In the following example, the two equal sub-arrays of B are compared and the two sub-arrays are determined to refer to the same elements:

if b[0...1] === b[0...1] {    println("These two subarrays share the same elements."else {    println("These two subarrays do not share the same elements.")}// 输出 "These two subarrays share the same elements."
Force copy Array

We force explicit replication by invoking the copy method of the array.  This method makes a shallow copy of the array (shallow copy), and returns a new array containing this copy. The following example defines a names array that contains seven names. A copiednames variable is also defined to store the results returned by the names copy method:

var names = ["Mohsen""Hilary""Justyn""Amy""Rich""Graham""Vic"]var copiedNames = names.copy()

We can determine that the names array has been copied by modifying one of the elements in the array and examining the corresponding elements in the other array. If you modify the first element in Copiednames from "Mohsen" to "Mo", the names array is still "Mohsen" before the copy occurs:

copiedName[0"Mo"println(name[0])// 输出 "Mohsen"

Note: If you only need to make sure that your reference to the array is a unique reference, call the Unshare method instead of the copy method. The Unshare method creates an array copy only if it is necessary. The Copy method creates a new copy at any time, even if the reference is already a unique reference.

iOS development Language Swift entry---classes and structs

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.