Swift Classes and structs

Source: Internet
Author: User
Tags class definition shallow copy

Suddenly someone asked me these two days what is the difference between the class and the structure in Swift?

Actually I am not very optimistic about Swift at present, I believe many people are also, OC is very mature.

I do not currently intend to delve into Swift's cause swift language has been out for a long time, but there are still a lot of things less stable than OC. Each version of Swift will have a larger change.

So just wait, wait until the work is not busy Swift also stabilized, and then look not too late.  But some things that are already stable inside can be understood first. Today is the next class and struct.

Http://c.biancheng.net/cpp/html/2427.html This website is good, the income is more detailed. Please go to this website for more information.

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
    • Define subscript for accessing values through the following banner method
    • Defining initializers for generating initialization values
    • Extended to add functionality to the default implementation
    • Compliance with protocols to provide standard functionality for a class


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
      • Canceling the initializer allows a class instance to free any resources it has been assigned
      • Reference count allows multiple references to a class
Note: Structs are passed through the code in a way that is copied, 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:

    1. Class SomeClass {
    2. Class definition goes here
    3. }
    4. struct Somestructure {
    5. Structure definition goes here
    6. }
Note: Each time you define a new class or struct, you are effectively defining a new Swift type. So use uppercamelcase this way to name (such as SomeClass and somestructure, etc.) in order 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:

    1. struct Resolution {
    2. var width = 0
    3. var heigth = 0
    4. }
    5. Class Videomode {
    6. var resolution = Resolution ()
    7. var interlaced = False
    8. var framerate = 0.0
    9. var name:string?
    10. }

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, each of which is a inteflaced with an initial value of false (meaning "non-interlaced video"). The playback frame rate initial value is 0.0 framerate and the value is the name of the optional string. 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:

    1. Let someresolution = Resolution ()
    2. Let Somevideomode = Videomode ()

Both structs and classes use the initializer syntax to generate new instances. The simplest form of initializer syntax is to follow an empty bracket, such as resolution () or Videomode (), after the type name of the struct or class. Any class or struct instance created in this way will be initialized to the default value. 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:

    1. println ("The width of someresolution is \ (someresolution.width)")
    2. Output "The width of someresolution is 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:

    1. println ("The width of Somevideomode is \ (someVideoMode.resolution.width)")
    2. Output "The width of Somevideomode is 0"

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

    1. SomeVideoMode.resolution.width = 12880
    2. println ("The width of Somevideomode is now \ (someVideoMode.resolution.width)")
    3. Output "The width of Somevideomode is now 1280"
Note: Unlike the Objective-c language, Swift allows you to set the child properties of a struct property directly. The last example above is to set the Somevideomode property of the resolution property directly, and the above operation does not need to set the resolution property from the new setting.
Member-by-initializer for struct type

All structs have an automatically generated member-by-initializer 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-initializer by the name of the property:

    1. Let VGA = Resolution (width:640, heigth:480)

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

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:

    1. Let HD = Resolution (width:1920, height:1080)
    2. 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:

    1. Cinema.width = 2048

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

    1. println ("Cinema is now \ (cinema.width) pixels wide")
    2. Output "Cinema is now 2048 pixels wide"

However, the width attribute in the original HD instance is still 1920:

    1. println ("HD is still \ (hd.width) pixels wide")
    2. Output "HD is still 1920x1080 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:

    1. Enum CompassPoint {
    2. Case North, South, East, West
    3. }
    4. var currentdirection = Compasspoint.west
    5. Let remembereddirection = Currentdirection
    6. Currentdirection =. East
    7. if rememberdirection = =. West {
    8. println ("The remembered direction is still. West ")
    9. }
    10. Output "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 assigned to a variable, a constant, or is passed to a function, and the operation is not a copy of it. 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:

    1. Let teneighty = Videomode ()
    2. Teneighty.resolution = HD
    3. Teneighty.interlaced = True
    4. Teneighty.name = "1080i"
    5. Teneighty.framerate = 25.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:

    1. Let alsoteneighty = Teneighty
    2. Alsoteneighty.framerate = 30.0

Because the class is a reference type, teneight and Alsoteneight actually refer to the same Videomode instance. In other words, they are just two of the same examples.

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:

    1. println ("The Framerate property of Teneighty was now \ (teneighty.framerate)")
    2. Output "The Framerate property of Theeighty was now 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 this 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, they 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:

    1. if teneighty = = = Alsotentighty {
    2. println ("Tentighty and Alsoteneighty refer to the same Resolution instance.")
    3. }
    4. Output "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.

As a general guideline, consider building a struct when one or more of the following conditions are met:

    • The main purpose of the structure 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.
    • Structs do not need to inherit the properties or behaviors of another existing type.


Suitable structural candidates include:

    • The size of the geometry, which encapsulates a width property and a height property, both of which are double types.
    • 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 set (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 behavior description of the array and structure is different from the behavior description of Nsarray and Nsdictionary, the latter is implemented in the form of a class, the former is implemented in the form of structure. 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.

    1. var = ["Peter": Ages, "Wei": +, "Anish": +, "Katya": 19]
    2. 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:

    1. Copiedages["peter"] = println (ages["Peter")//Output "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:

    1. var a = [1, 2, 3]
    2. var B = A
    3. var C = A

We can use the following banner on A,b,c to get the first element of the array:

    1. println (A[0])
    2. 1
    3. println (B[0])
    4. 1
    5. println (c[0])//1

If you modify the value of an element in an array by following the banner, the corresponding value in the 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:

    1. A[0] = 42
    2. println (A[0])
    3. 42
    4. println (B[0])
    5. 42
    6. println (C[0])
    7. 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 value of the element in a again, a will return a different result than the b,c, since the two refer to the original array:

    1. A.append (4)
    2. A[0] = 777
    3. println (A[0])
    4. 777
    5. println (B[0])
    6. 42
    7. println (C[0])
    8. 42
Ensure the uniqueness of the array

It is necessary to make sure that the array has a unique copy before manipulating an array or passing it to a function and a method call. The uniqueness of the array reference is determined by calling the Unshare method on the array variable. (The Unshare method cannot be called when the 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:

    1. 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:

    1. B[0] = 105
    2. println (A[0])
    3. 77
    4. println (B[0])
    5. -105
    6. println (C[0])
    7. 42
Determines whether two arrays share the same element

We use the identity operator (identity operators) (= = = and!==) to determine that two arrays or sub-arrays share the same storage space or elements.

The following example uses the constant equals (identical to) operator (= = =) to determine whether B and C share the same array elements:

    1. if b = = = c {
    2. println ("B and C still share the same array elements.")
    3. } else {
    4. println ("B and C now refer to" independent sets of array elements. ")
    5. }
    6. Output "B and C now refer Totwo independent sets of 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:

    1. If b[0...1] = = = B[0...1] {
    2. println ("These-subarrays share the same elements.")
    3. } else {
    4. println ("These-subarrays does not share the same elements.")
    5. }
    6. Output "These 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 the 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:

    1. var names = ["Mohsen", "Hilary", "Justyn", "Amy", "Rich", "Graham", "Vic"]
    2. var copiednames = names.copy

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

    1. Copiedname[0] = "Mo"
    2. println (Name[0])
    3. Output "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.

Swift 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.