A declaration can introduce new names and constructs into your program. ** For example, you can use declarations to introduce functions and methods, variables and constants, or to define new named enumerations, structures, classes and protocol types. You can also use a declaration to extend the behavior of an existing named type. Or introduce symbols that are declared elsewhere in your program.
In SWIFT, most declarations are also, in some sense, initial definitions of execution or colleague declarations. This means that, because protocols and their members do not match, most protocol members require separate declarations. For convenience, and because these differences are not so important in SWIFT, declaration statements contain both the declaration and the definition.
GRAMMAR OF A DECLARATION → import-declaration → constant-declaration → Variable-declaration → typealias-declaration → function-declaration → Enum -declaration → struct-declaration → class-declaration → protocol-declaration Declaration → initializer-declaration declaration → deinitializer-declaration declaration → extension-declaration Declaration – subscript – declaration declaration – > operator – declaration declarations > declarationdeclarationsopt Declaration – specifiers – > declaration – specifierdeclaration – specifiersopt declaration – specifiers – class | mutating | nonmutating | override | static | unowned |
Scope of the module
A module scope defines code that is visible to other source files in the module. The highest level of code in the Swift source file consists of zero or more statements, declarations and expressions. Variables, constants, and other declarations are declared at the top level of a source file, making them visible to every source file in the same module.
GRAMMAR OF A top-level DECLARATION → statements opt
The code block
Code blocks are used to group together statements that declare and control structures. It has the following form:
1. { `statements` }
Copy the code
Statements in a code block include declarations, expressions, and various other types of statements that are executed in the order in which they appear in the source code.
GRAMMAR OF A CODE BLOCK CODE – BLOCK → statements opt
Introduce statement
Introducing declarations allows you to use content declared in other files. The basic form of an import statement is to introduce the entire code module; It starts with the import keyword followed by a module name:
1. import module
Copy the code
You can limit the incoming notation by providing more detail, such as declaring a special submodule or making special declarations within a module or submodule. After you use these details, only the introduced symbols are available in the current program summary (not the entire module declared).
1. import import kind module.symbol name import module.submodule
Copy the code
GRAMMAR OF AN IMPORT DECLARATION import-declaration → Attributes opt IMPORT import-kind opt import-path import-kind → Typealias | struct | class | enum | protocol | var | func import – path – import – path – identifier Import-path-identifier. Import-path import-path-identifier → identifier operator
Constant statement
Constant declarations can name a constant in your program. Constants are declared with the keyword let, following the following format:
1. let constant name: type = expression
Copy the code
When the value of the constant is given, the constant combines the name of the constant with the initial value of the expression and cannot be changed. This means that if a constant is initialized as a class, the contents of the class itself can be changed, but the association between the constant and the class cannot be changed. When a constant is declared as a global variable, it must be given an initial value. When a constant is declared in a class or structure, it is considered a constant property. Constants are not computable properties and therefore do not contain getters and setters. (Getters and setters)
If the constant name is of a primitive form, each item in the primitive must have its corresponding value in the initialization expression
1. let (firstNumber, secondNumber) = (10, 42)
Copy the code
In the above example, firstNumber is a constant with a value of 10, and secnodeName is a constant with a value of 42. All constants can be used independently:
1. 1 println("The first number is \(firstNumber).")
2 // prints "The first number is 10."
3 println("The second number is \(secondNumber).")
4 // prints "The second number is 42."
Copy the code
The type annotation (:type), which is optional in the constant declaration, can be used to describe types found in the Type inference interface.
To declare a static constant, use the keyword static. Static attributes are described in Type Attributes (Type Propetries).
For more information on constants or help with using them, check out the Sections Constants and Variables, Stored Properties, and more.
GRAMMAR OF A CONSTANT DECLARATION constant-declaration → Attributes opt DECLARATION -specifiers opt Letpattern –, initializer list pattern -, initializer list – the pattern -, initializer | pattern -, initializer, Pattern -initializer-list pattern- Initializer → Pattern Initializer opt Initializer → =expression
Data Collection Office
Variable declarations
You can declare a variable in your program using the keyword var. Declarations vary depending on the type and value of the declared variable, such as storing and calculating variables and properties, storing variables and properties monitoring, and static variable properties. The form of declaration used depends on the scope of the variable declaration and the type of variable you intend to declare.
Note: You can also declare properties in the context of a protocol declaration. See Type Property declaration for details.
Stored variables and stored properties
The following form declares a stored variable or a stored variable attribute
1. var variable name: type = expression
Copy the code
You can use this form to declare a variable globally, within a function, or within a class or structure declaration (context). When a variable is declared in this form globally or within a function, it represents a stored variable. When declared in a class or structure, it represents a stored variable property.
Constructor expressions can be compared to constant declarations. If the variable name is of a meta-type, each entry in the meta-type must have the same name as the initialization expression.
As the name implies, the value or attribute of a stored variable is stored in memory.
Computational variables and computational attributes
Declare a stored variable or a stored property in the following form:
1. var variable name: type { get { statements } set(setter name) { statements } }
Copy the code
You can use this form of declaration in the context of global, function body, or class, structure, enumeration, or extension declarations. When a variable is declared in this form globally or within a function, it represents a computed variable. When it is declared in the context of a class, structure, enumeration, or extension declaration, it represents a computed variable property.
Getters are used to read values, setters are used to write values. The setter clause is optional, only the getter is required, and you can omit all of these statements and simply return the request value directly, as described in Read-only Computed Properties. But if you provide a setter statement, you must also provide a getter statement.
The name of the setter and the statement in parentheses are optional. If you write a setter name, it’s going to be used as an argument to the setter. If you don’t write the setter name, the initial name of the setter is newValue, as mentioned in seter shorthand.
Unlike stored variables and stored attributes, the values of computed attributes and computed variables are not stored in memory.
For more information and to see more examples of computed properties, see the computed Properties section.
Stored variable monitor and property monitor
You can declare a storage variable or property using the WillSET and didSet monitors. A stored variable or property containing the monitor is declared as follows:
1. var variable name: type = expression { willSet(setter name) { statements } didSet(setter name { statements } }
Copy the code
You can use this form of declaration in the context of global, function body, or class, structure, enumeration, or extension declarations. When variables are declared in this form globally or within a function, the monitor represents a stored variable monitor; The monitor represents the property monitor when it is declared in the context of a class, structure, enumeration, or extension declaration.
You can add any storage properties for the appropriate monitor. You can also add any inherited properties (whether stored or computational) to the appropriate monitor by overriding the subclass properties, see Unifying properyt Observers.
An initialization expression is optional in the declaration of a class or structure, but is required elsewhere. No matter where they are declared, all variable declarations that contain a monitor must have type annotations.
The WillSET and DIDSet monitors provide a way to monitor (appropriately respond) when the value of a variable or property is changed. Monitors are not run when a variable or property is first initialized; they are only run when the value is changed by an external initialization statement.
The willSet monitor runs only before variable or property values are changed. The new value passes through the WillSet monitor as a constant, so it cannot be changed in the willset statement. The DIDSET monitor runs immediately after a variable or property value has been changed. In contrast to the willSet monitor, the old variable value or property passes through the DIDSet monitor in case you still need to get the old data. This means that if you set a value in the didiset monitor statement of the variable or property itself, the new value you set will replace the value you just passed in the WillSet monitor.
In the willSET and didSET statements, the statement for the setter name and parentheses is optional. If you write a setter name, it’s going to be used as the willset and didSet arguments. If you don’t write the setter name, willset monitor initial name is newValue, didSet monitor initial name is oldValue.
The DIDSET statement is optional when you provide a willset statement. Also, when you provide a didSET statement, the willset statement is optional.
For more information and an example of how to use property monitors, see the section Prpperty Observers.
Class and static variable properties
The class keyword is used to declare computational properties of a class. The static keyword is used to declare static variable properties of a class. Classes and static variables are discussed in detail in Type Properties.
GRAMMAR OF A VARIABLE DECLARATION VARIABLE – DECLARATION → VARIABLE -headpattern- Initializer-list Variable -declaration → variable-declaration-head variable-name type-annotation code-block variable-declaration → Variable-declaration-head variable-name type-annotation getter-setter-block variable-declaration → Variable-declaration-head variable-name type-annotation getter-setter-keyword-block variable-declaration → Varial-declaration-head varial-name type-annotationInitializer opt willSet-didSet-block varial-declaration-head → Attributes opt declaration-speciFIERS opt var varible-name → identifier getter-setter-block → {getter-clause Setter-clause opt} getter-setter-block → {setter-clause getter-clause} getter-clause → attributes optgetcode-block Setter-clause → attributes opt set setter-name opt code-block setter-name → (identifier) getter-setter-keyword block → {getter-keyword-clause setter-keyword-clause opt} getter-setter-keyword-block → {setter-keyword-clause Getter-keyword-clause → attributes opt get setter-keyword-clause → attributes opt set Willset-didset-block → {willset-clause didset-clause opt} willset-didset-block → {didset-clause willset-clause} Willset-clause → attributes opt willSet setter-name opt code-block didset-clause → attributes opt didSet setter-name opt code-block
An alias declaration for a type
A type alias declaration can declare an alias for an existing type in your program. The alias declaration for a type starts with the keyword typeAlias and follows the following form:
1. typealias name = existing type
Copy the code
When a type is declared by an alias, you can replace the existing type with the alias anywhere in your program. An existing type can be a named type or a mixed type. An alias for a type does not create a new type, it is simply a name replacement with an existing type.
Check out more Protocol Associated Type Declarations.
GRAMMAR OF A TYPE ALIAS DECLARATION typealia-declaration → typealia-head typealia-assignment typealia-head → Typealias Typealias-name Typealias-name → identifier Typealia-assignment → =type
Function declaration
You can use function declarations to introduce new functions into your program. Functions can be declared in the context of a class, as a structure, as an enumeration, or as a method protocol. The function declaration uses the keyword func and follows the following form:
1. func function name(parameters) -> return type { statements }
Copy the code
If the function does not return any value, the return type can be ignored, as shown below:
1. func function name(parameters) { statements }
Copy the code
The type of each parameter must be specified, and they cannot be inferred. The initial arguments to the function are constant values. Adding var in front of these arguments makes them variables. Any changes to the variables in the scope are only valid in the body of the function, or those made with inout can be valid in the calling domain. For more on in-out parameters, see In-out parameters.
A function can return multiple variables using the tuple type as its return value.
A function definition can appear within another function declaration. This function is called a nested function. For more on nested functions, see Nestde functions.
Parameter names
The arguments to the function are a comma-separated list. The order of variables in a function call must be the same as the order of arguments in a function declaration. The simplest argument list has the following form:
1. parameter name: parameter type
Copy the code
For function arguments, the parameter name is used within the function body, not during the function call. For method parameters, the parameter name is used inside the function body and as a label when the method is called. The first parameter name of the method is used only in the body of the function, just like the parameters of the function. For example:
1. func f(x: Int, y: String) -> String { return y + String(x) } f(7, "hello") // x and y have no name class C { func f(x: Int, y: }} let c = c () c.f (7, y: "hello") // let c = c () c.f (7, y: "hello"Copy the code
You can override the procedure where the parameter name is used as follows:
1. external parameter name local parameter name: parameter type #parameter name: parameter type
_ local parameter name: parameter type
Copy the code
The second name named before the local parameter gives the parameter an extension. The parameter name is different from the local parameter name. Extended parameter names must be used when the function is called. The corresponding argument must have an extension when the method or function is called.
The hash symbol (#) written before the parameter name indicates that the parameter name can be used as both external and ontology parameter names. This is equivalent to writing the local parameter name twice. When a function or method is called, the statement corresponding to it must contain this name.
The accent character (_) before the local parameter name causes the parameter to have no name when the function is called. When a function or method is called, the statement corresponding to it must have no name.
Parameter of special type
Parameters can be ignored, values can vary, and an initial value is provided. This method has the following form:
1. _ : <#parameter type#. parameter name: parameter type... parameter name: parameter type = de
fault argument value
Copy the code
Arguments named with the underscore (_) are explicitly not accessible within the function body.
A parameter with the underlying type name, if followed by three dots (…) Is understood to be a variable parameter. A function can have at most one variable argument, which must be the last argument. The mutable parameters are treated as an array of the basic type names. For example, the variable parameter int… Is treated as int[]. For details about how to use variadic Parameters, see section Variadic Parameters.
An expression followed by an equal (=) sign after the type of the argument is considered to have the initial value of the given expression. If the argument is omitted during the function call, the initial value is used. If the argument has no win rate, then it must have its own name in the function call. For example, both f() and f(x:7) are valid calls to a function with a single variable x, but f(7) is illegal because it provides a value instead of a name.
Special methods
Enumeration or struct methods decorated with self must have a mutating keyword as the function declaration header.
Methods overridden by subclasses must have the override keyword as the function declaration header. Methods that are overridden without the override keyword will report an error if they use the override keyword but do not override the parent method.
Methods that are related to a type rather than an instance of a type must be in a static declared structure or enumeration, or in a class defined with the class keyword.
Corylization functions and methods
A Curryization function or method has the following form:
1. func function name(parameters)(parameters) -> return type { statements }
Copy the code
The return value of a function defined in this form is another function. For example, the following two statements are equivalent:
1. func addTwoNumbers(a: Int)(b: Int) -> Int { return a + b } func addTwoNumbers(a: Int) ->
(Int -> Int) { func addTheSecondNumber(b: Int) -> Int { return a + b } return addTheSecondNumber }
addTwoNumbers(4)(5) // Returns 9
Copy the code
The application of multistage currying is as follows
GRAMMAR OF A FUNCTION DECLARATION function-declaration → function-head function-name generic-parameter-clause Optfunction-signature function-body function-head → attributes opt declaration-specifiers optfunc function-name → Identifier operator function-signature → parameter-clauses function-result opt function-result → -> Attributes opt type Function-body → code-block parameter-clause → parameter-clause → () (parameter-list… Opt) parameter-list → parameter parameter,parameter-list parameter → inout opt let opt#optparameter-name Local-parameter -name opt type-annotation default-argument-clause opt parameter → Inoutoptvar# optparameter-namelocal-parameter-name opt type-annotationdefault-argument-clause optparameter → attributes Opt type parameter-name → identifier _ local-parameter-name → identifier _ default-argument-clause → =expression:
Enumeration declarations
Use an enumeration declaration in your program to introduce an enumeration type.
Enumeration declarations come in two basic forms, declared using the keyword enum. Enumeration bodies use zero-based variables — called enumeration events — and any number of declarations, including computed attributes, instance methods, static methods, constructors, type aliases, and even other enumerations, structs, and classes. Enumeration declarations cannot contain destructor or protocol declarations.
Not like a class or a structure. Enumerated types do not provide an implicit initializer; all constructors must be explicitly declared. Constructors can delegate to other constructors in an enumeration, but the construction process is complete only after the constructor completes an enumeration.
Like structs but unlike classes, enumerations are value types: enumeration instances are copied when assigned variables or constants, or when called by functions. For more information about Value Types, see the section Structures and Enumerations Are Value Types.
You can extend enumerated types, as discussed in the Extension Declaration.
Enumeration of any event type
The following form declares an enumeration variable that contains any type of enumeration time
1. enum enumeration name { case enumeration case 1 case enumeration case 2(associated value
types) }
Copy the code
This form of enumeration declaration is sometimes called discrinminated in other languages.
In this form, each event block starts with the keyword case, followed by one or more comma-separated enumerated events. Each event name must be unique. Each event can also specify the type of value it stores. These types are specified in the ancestor of the associated value type, immediately written after the event name. For more information and examples about associated value types, see the Associated Values section.
Use an enumeration of the original event values
The following form declares an enumeration containing enumeration events of the same base type:
1. enum enumeration name: raw value type { case enumeration case 1 = raw value 1 case enumeratio
n case 2 = raw value 2 }
Copy the code
In this form, each event block starts with the case keyword, followed by one or more comma-separated enumeration events. Unlike the first form of an enumeration event, this form of an enumeration event contains a base value of the same type, called a raw value. The type of these values is specified in the Raw Value type and must be a literal integer, float, character, or string.
Each event must have a unique name and must have a unique initial value. If the initial value type is specified as int, there is no need to explicitly specify the value for the event; they are implicitly labeled as values 0,1,2, etc. Every unassigned Int is implicitly given an initial value, and they are automatically incremented.
1. num ExampleEnum: Int { case A, B, C = 5, D }
Copy the code
In the above example, ExampleEnum.A has A value of 0 and ExampleEnum.B has A value of. Because the value of ExampleEnum.C is explicitly set to 5, the value of ExampleEnum.D automatically grows to 6.
The initial value of the enumeration event can be obtained by calling the method roRaw, such as ExampleEnum.b.toaw (). You can also call the fromRaw method to find the corresponding event using the initial value and return an optional event. For more information and to get information about initial value type events, see Raw Values.
Get enumeration event
Using dot (.). To refer to the enumeration types of events, such as EnumerationType EnumerationCase. When an Enumeration type can be inferred from the context, you can omit it (the. Is still required), referring to Enumeration Syntax and Implicit Member Expression.
Use a switch Statement to verify the value of an Enumeration event, as described in the section Matching Enumeration Values with a Switch Statement.
Enumeration type is pattern-matched. The opposite of Enumeration event matching in the case block of the switch statement is described in the Enumeration case pattern.
GRAMMAR OF AN ENUMERATION DECLARATION enum- DECLARATION → Attributesoptunion -style-enum Attributesoptraw -value-style-enum Union -style-enum → enum-namegeneric-parameter-clauseopt{union-style-enum-membersopt} union-style-enum-members → Union -style-enum-memberunion-style-enum-membersopt union-style-enum-member → declaration union-style-enum-case-clause Union style-enum-case-clause → AttributesoptCaseunion -style-enum-case-list union-style-enum-case-list → The union – style – enum – case union – style – enum – case, the union – style – enum – case – the list union – style – enum – case – > Enum -case-nametuple-typeopt enum-name → identifier enum-case-name → identifier raw-value-style-enum → Enum – namegeneric – parameter – clauseopt: type – identifier (raw value – style – enum – membersopt} raw – value – style – enum – members – > Raw – value – style – enum memberraw – value – style – enum – membersopt raw – value – style – enum – member – > declaration Raw – value – style – enum – case – clause raw – value – style – enum – case – clause – attributesoptcaseraw – value – style – enum – case – the list Raw – value – style – enum – case – the list – raw – value – style – enum – case raw – value – style – enum – case, raw – value – style – enum – case – the list Raw-value-style-enum -case → enum-case-nameraw-value-assignmentopt raw-value-assignment → =literal
Struct declaration
Use the struct declaration to introduce a struct type into your program. Struct declarations use the struct keyword and follow the following form:
1. struct structure name: adopted protocols { declarations }
Copy the code
The structure body contains zero or more declarations. These declarations can include stored and computed attributes, static attributes, instance methods, static methods, constructors, type aliases, and even other struct, class, and enumeration declarations. A struct declaration cannot contain a destructor or protocol declaration. See the classes and Structures section for a detailed discussion and an instance that includes multiple struct declarations.
A structure can contain any number of protocols, but it cannot inherit from a class, enumeration, or other structure.
There are three ways to create an instance of a declared structure:
– Calls constructors declared in the constructor body. See the Initializers section. — If no constructor is declared, call the struct’s constructors one-by-one. See Memberwise Initializers for Structure Types for details. — If no destructor is declared, all properties of the Structure have initial values and call the default constructor for the Structure. See the Default Initializers for details. See the initiaization section for the construction process of the structure. Struct instance properties can be used with points (.) See the section Accessing Properties for more details. A structure is a value type; An instance of a structure is copied when it is assigned a variable or constant and is called by a function. For more information about Value Types, see the section Structures and Enumerations Are Value Types. You can extend the behavior of a struct type with an Extension Declaration. See Extension Declaration.
GRAMMAR OF A STRUCTURE DECLARATION struct-declaration → Attributesoptstructstruct – namegeneric – parameter – clauseopttype – inheritance – clauseoptstruct – body struct – name – identifier Struct – body – > {declarationsopt}
Class declaration
You can use a class declaration in your program to introduce a class. Class declarations use the keyword class and follow the following form:
1. class class name: superclass, adopted protocols { declarations }
Copy the code
One class contains zero or more declarations. These declarations can include stored and computed attributes, instance methods, class methods, constructors, individual destructor methods, type aliases, and even other struct, class, and enumeration declarations. Class declarations cannot contain protocol declarations. See the classes and Structures section for a detailed discussion and an instance that includes multiple kinds of declarations.
A class can inherit only one parent, superclass, but can contain any number of protocols. These superclasses first appeared in type-inheritance-clause, which follows any agreement.
As mentioned in the Initializer Declaration, classes can have specified and convenient constructors. When you declare any of the constructors, you can flag the constructor with the requierd variable, requiring any subclass to override it. The constructor that specifies a class must initialize all declared properties of the class, which must be executed before a subclass constructor is called.
A class can override properties, methods, and constructors of its superclass. Overridden methods and properties must be annotated with Override.
Although the property and method declarations of a superclass can be inherited by the current class, the specified constructor declared by the superclass cannot. This means that if the current class overrides all the specified constructors of the superclass, it inherits the convenience constructors of the superclass. Swift’s classes do not inherit from a global base class.
There are two ways to create an instance of a declared class:
- Calls a constructor of the class. See Initializers.
- If no constructor is declared and all properties of the class are given initial values, call the class’s default constructor. See Default Initializers.
Class instance attributes can be used with the dot (.) See the section Accessing Properties for more details.
Classes are reference types; When given a constant or variable, or when a function is called, an instance of the class is referenced, not copied. For more information about reference Types, Structures and Enumerations Are Value Types.
You can use an Extension Declaration to extend the behavior of a class. See Extension Declaration.
GRAMMAR OF A CLASS DECLARATION class-declaration → Attributesoptclassclass – namegeneric – parameter – clauseopttype – inheritance – clauseoptclass – body class – the name and identifier Class – the body – > {declarationsopt}
Statement of Agreement
A protocol declaration introduces a named protocol type to your program. Protocol declarations are made using the protocol keyword and have the following form:
1. protocol protocol name: inherited protocols {
2. protocol member declarations
3. }
Copy the code
The body of a protocol contains zero or more protocol member declarations that describe the conformance requirements that must be met by any adoption of the protocol. In particular, a protocol may declare that certain conformance types of properties, methods, initializers, and ancillary scripts must be implemented. Protocols can also declare type aliases of specific classes, called association types, which specify the relationship between different declarations of the protocol. The agreement membership declaration is discussed in the details below.
A protocol type can inherit from many other protocols. When a protocol type inherits from another protocol, all requirements from the other protocol are assembled, and any type inheriting from the current protocol must meet all of these requirements. For an example of how to use protocol inheritance, see Protocol inheritance
Note: You can also use protocol composition types to set conformance requirements for multiple protocols. See Protocol Composition Types and Protocol Composition for details
You can add protocol consistency to previously declared types by adopting the protocol in the type’s extension declaration. You must implement all of the protocol adoption requirements in the extension. If the type has fulfilled all the requirements, you can leave the subject of the extension declaration blank.
By default, the types that conform to a protocol must implement all the properties, methods, and ancillary scripts declared in the protocol. That is, you can annotate these protocol member declarations with the optional attribute to specify that their conformance type implementation is optional. The optional property can only be used for protocols marked with objC properties. The result is that only class types can adopt and comply with protocols that contain optional member requirements. For more information on how to use the optional attribute and guidance on how to access optional protocol members — such as when you’re not sure if a consistent type implements them — see Optional Protocol Requirements
To limit protocol adoption to class types only, you need to mark the entire protocol declaration with the class_protocol attribute. Any protocol that inherits from a protocol marked with the class_protocol attribute can be intelligently adopted only by class types.
Note: The class_protocol attribute is implicitly applied to a protocol if the protocol is already marked with an object attribute; It is no longer necessary to explicitly mark the protocol with the class_protocol attribute.
Protocols are named types, so they can appear everywhere in your code as another named type, as discussed in protocol types. However, you cannot construct an instance of a protocol because protocols do not actually provide implementations of the requirements they specify.
You can use protocols to declare the methods or structures that a class’s proxy should implement, as described in the delegate (proxy) pattern.
Agreement statement syntax protocol – declaration – attributesoptprotocolprotocol – nametype – inheritance – clauseoptprotocol – body protocol – name – > Identifier protocol-body → {protocol-member-declarationsopt} protocol-member-declaration → Protocol-property-declaration protocol-member-declaration → protocol-method-declaration protocol-member-declaration → Protocol, initializer – declaration protocol – member – declaration – protocol – subscript – declaration Protocol-member-declaration → protocol-association-type-declaration protocol-member-declarations → protocol-member-declarationprotocol-member-declarationsopt
Protocol Attribute Declaration
Protocol declaration conformance types must implement an attribute by introducing a protocol attribute declaration in the body of the protocol declaration. Protocol attribute declarations have a special type declaration form:
1. var property name: type { get set }
Copy the code
Like other protocol member declarations, these property declarations declare getter and setter requirements only for types that conform to the protocol. The result is that you don’t need to implement getters and setters in the protocol where it’s declared.
Getter and setter requirements can be satisfied in various ways through consistency types. If the property declaration contains the get and set keywords, the consistency type can use a stored variable property or a computed property that is read and write (implementing the getter and setter), but the property cannot be implemented as a constant property or a read-only computed property. If the property declaration contains only the get keyword, it can be implemented as a property of any type. For example, a consistency type that implements the attribute requirements of the protocol, see attribute requirements
See Variable declaration for more information
Protocol property declaration protocol property-declaration → variable-declaration-headvariable-nametype-annotationgetter-setter-keyword-block
Protocol Method declaration
Protocol declaration conformance types must implement a method by introducing a protocol method declaration in the body of the protocol declaration. Protocol method declarations and function method declarations have the same form, with the following two rules: they do not include function bodies, and you cannot provide initial values for their arguments in the class declaration. For example, the conforming types execute the methods required by the protocol. See the required Methods section.
Use the keyword class to declare a class or required static methods in a protocol declaration. The classes that execute these methods are also declared with the keyword class. Instead, the structure that executes these methods must be declared with the keyword static. If you want to use extension methods, use the class keyword when extending a class and the static keyword when extending a structure.
See function declaration for more information.
GRAMMAR OF A PROTOCOL METHOD DECLARATION
protocol-method-declaration → function-headfunction-namegeneric-parameter-clauseoptfunction-signature
Protocol constructor declaration
Protocol declaration conformance types must implement a constructor by introducing a protocol constructor declaration in the body of the protocol declaration. A protocol constructor declaration has the same form as a constructor declaration except that it does not contain a constructor. For more information, see Constructor declaration.
GRAMMAR OF A PROTOCOL INITIALIZER DECLARATION PROTOCOL – INITIALIZER – DECLARATION → initializer-headgeneric-parameter-clauseoptparameter-clause
Protocol affiliate script declaration
Protocol declaration conformance types must implement a protocol affiliate script declaration in the body of the protocol declaration by introducing a protocol affiliate script declaration. Protocol attribute declarations have a special form for attach-script declarations:
subscript (parameters) -> return type { get set }
The subsidiary script declaration declares only the minimum number of getters and setters required for the type that is consistent with the protocol. If the accessory script declaration contains the get and set keywords, the consistent type must also have a getter and setter statement. If the accessory script declares that the value contains the GET keyword, the consistent type must contain at least one getter statement and optionally a setter statement.
See attached script declarations for more information.
GRAMMAR OF A PROTOCOL SUBSCRIPT DECLARATION protocol-subscript- DECLARATION → subscript-headsubscript-resultgetter-setter-keyword-block
Protocol related type declaration
The protocol declares related types using the keyword TypeAlias. The related type provides an alias for the type that is part of the protocol declaration. Related types are similar to type parameters in parameter statements, but they contain the self keyword in the declared protocol. In these statements, self refers to possible types that are consistent with the protocol. For more information and examples, see related type or type alias declarations.
GRAMMAR OF A PROTOCOL ASSOCIATED TYPE DECLARATION
protocol-associated-type-declaration → typealias-headtype-inheritance-clauseopttypealias-assignmentopt
Constructor declaration
A constructor declaration introduces a constructor for a class, structure, or enumeration within a program. The constructor is declared using the keyword Init, following two basic forms.
Structs, enumerations, classes can have any number of constructors, but the rules and behavior of class constructors are different. Unlike constructors and enumerators, there are two types of classes, designed Initializers and convenience Initializers. See section Constructors.
The following form declares the specified constructor for the structure, enumeration, and class:
1. init(parameters) { statements }
Copy the code
The specified constructor of a class initializes all properties of the class directly. If a class has a superclass, it cannot call other constructors of that class. It can only call one of the specified constructors of the superclass. If a class inherits any properties from its superclass, those properties must be assigned or decorated within the current class with the specified constructor of the superclass.
The specified constructor can be declared in the context of a class declaration, so it cannot be added to a class with methods that extend the declaration.
Constructors for structs and enumerations can delegate all initialization to one of them, along with other declared constructors.
Declare a convenience constructor for a class with the keyword convenience:
1. convenience init(parameters) { statements }
Copy the code
A convenience constructor can delegate the initialization process to another convenience constructor or to a specified constructor of a class. This means that the class initialization process must end with a call to the specified constructor that fully initializes all class attributes. A convenience constructor cannot call the constructor of a superclass.
You can use the requierd keyword to mark the convenience constructor and the specified constructor as mandatory for each subclass constructor. Because specified constructors are not inherited by subclasses, they must be executed immediately. When a subclass directly executes all the specified constructors of the superclass (or overwrites the specified constructors with a convenience constructor), the required convenience constructors can be executed implicitly or inherited. Unlike methods and attached scripts, you do not need to tag the overrride keyword for these overridden constructors.
See the Construction Procedure section for more examples of constructors that declare different methods.
GRAMMAR OF AN INITIALIZER DECLARATION INITIALIZER – DECLARATION → , initializer headgeneric – parameter – clauseoptparameter – clauseinitializer – body, initializer – head – > Attributesoptconvenienceoptinit, initializer – body – > code – block
Destructor statement
A destructor declaration declares a destructor for a class. Destructors take no arguments and follow the following format:
1. deinit { statements }
Copy the code
The destructor is automatically called when the class is about to be released without any statements. Destructors can only be declared once in the body of a class declaration — but not in the extended declaration of a class, and there can be at most one per class.
A subclass inherits a destructor from its superclass, which is called implicitly when the subclass is about to be released. Subclasses are not released until all destructors have been executed.
Destructors are not called directly.
To see examples and how to use destructors in class declarations, see the destructor procedure section.
GRAMMAR OF A DEINITIALIZER DECLARATION DEINITIALIZER – DECLARATION → AttributesoptDeinitcode -block
Extension declaration
An extension declaration is used to extend the behavior of an existing class, structure, or enumeration. Extension declarations start with the keyword extension and follow the following rules:
1. extension type: adopted protocols { declarations }
Copy the code
An extended declaration body contains zero or more declarations. These declarations can include computed properties, computed static properties, instance methods, static and class methods, constructors, auxiliary script declarations, and even other structs, classes, and enumeration declarations. Extension declarations cannot contain destructors, protocol declarations, stored properties, property monitors, or other extended properties. See the Extensions section for a detailed discussion and review of instances that contain multiple extension declarations.
Extension declarations can add consistent protocols to existing classes, structures, and enumerations. Extension declarations cannot add inherited classes to a class, so type-inheritance-clause is an extension declaration that contains only a list of protocols.
Properties, methods, and constructors of existing types cannot be overridden by extensions of their types.
Extension declarations can include constructor declarations, which means that if your extension type is defined in another module, the constructor declaration must delegate to another constructor declared in that module to properly initialize it.
GRAMMAR OF AN EXTENSION DECLARATION extension-declaration → Extensiontype identifiertype – inheritance – clauseoptextension – body extension – the body – > {declarationsopt}
Attachment script Declaration
Affiliate scripts are used to add support for affiliate scripts to specific types, typically providing syntactic convenience for accessing elements of collections, lists, and sequences. A subsidiary script declaration uses the keyword subscript and takes the following form:
Subscript (parameter) -> (return type){get{statements} set(setter name){statements}} Subscript (parameter) -> (return type){get{statements} set(setter name){statements}} Extensions are declared in the context of the protocol declaration.
Parameters specify one or more indexes (for example, I in the expression object[I]) that are used to access the element in the dependent script of the related type. Although the indexes used for element access can be of any type, each variable must contain a type annotation that specifies each index type. Return type Specifies the type of the element being accessed.
As with computational attributes, attachment script declarations support read and write operations on access elements. Getters are used to read values, setters are used to write values. The setter clause is optional; when only one getter clause is needed, you can ignore both and simply return the requested value. That is, if the setter clause is used, the getter clause must be used.
The name of the setter and the enclosing parentheses are optional. If the setter name is used, it will be treated as the name of the variable passed to the setter. If the setter name is not used, then the name of the variable passed to the setter defaults to value. The setter name must be of the same type as the return type.
You can override the dependency script within the type it declares, as long as the parameters or return type are different from the previous one. At this point, you must declare the overridden subsidiary script using the override keyword. (Note: What a mess! Is it overloading or overwriting? !).
Subsidiary scripts can also be declared in the context of a Protocol Declaration, as described in the Protocol Subscript Declaration.
For more examples of attached scripts and attached script declarations, see Subscripts.
GRAMMAR OF A SUBSCRIPT DECLARATION subscript-declaration → Subscript-headsubscript-resultcode-block Subscript-declaration → subscript-headSubscript-resultgetter-setter-block subscript-declaration → Subscript headsubscript – resultgetter – setter – keyword – block subscript – head – > attributesoptsubscriptparameter – clause Subscript – result – > – > attributesopttype
Operator declaration
Operator declarations introduce infix, prefix, or postfix operators into the program, using the context keyword operator declaration. Three different fixes can be declared: infixes, prefixes, and suffixes. The affix of an operator describes the position of the operator relative to its operands. There are three basic forms of operator declarations, one for each modifier. The fixability of an operator is specified by adding the context keyword infix, prefix, or postfix between operator and operator. In each form, the name of the operator can contain only the operator characters defined in Operators.
The following form declares a new infix operator:
operator infix operator name{ precedence precedence level associativity associativity }
The infix operator is a binary operator that can be placed between two operands, such as the addition operator (+) in the expression 1 + 2.
The infix operator can optionally specify precedence, associativity, or both.
The precedence of an operator specifies how tightly the operator is bound to its operands without parentheses. You can use the context keyword precedence together with the precedence level to specify the precedence of an operator. The priority can be any number between 0 and 255 (a decimal integer); Unlike decimal integer literals, they cannot contain any underscore characters. Although the priority is a specific number, it is only used for comparison (size) with another operator. That is, when an operand can be used by two operators at the same time, such as 2 + 3 * 5, the operator with higher precedence will bind to the operand first.
Operator associativity specifies the order in which operators of the same precedence are grouped without parentheses. The associativity of an operator can be specified using the context keyword associativity together with associativity, where associativity can be any of the context keywords left, right, or None. Left-associative operators are grouped from left to right. For example, the subtraction operator (-) is left associative, so 4-5-6 is grouped in the form (4-5) -6, which results in -7. Right-associative operators are grouped from right to left, and for non-associative operators set to None, they are not grouped in any way. Non-associative operators with the same precedence may not be adjacent to each other. For example, the expression 1 < 2 < 3 is illegal.
Infix operators that do not specify any precedence or associative, are initialized to 100 and none to associative.
The following form declares a new prefix operator:
operator prefix operator name{}
The prefix operator immediately preceding the operand is a unary operator, such as the prefix increment operator (++) in the expression ++ I.
No priority is specified in the declaration of the prefix operator. The prefix operator is nonassociative.
The following form declares a new suffix operator:
operator postfix operator name{}
The postfix operator that follows the operand is a unary operator, such as the prefix-increment operator (++) in the expression i++.
As with the prefix operator, the suffix operator does not specify a priority in its declaration. The postfix operator is nonassociative.
After you declare a new operator, you need to declare a function with the same name as the operator to implement the operator. To implement a new operator, see Custom Operators.
GRAMMAR OF AN OPERATOR DECLARATION operate-declaration → prefix-operate-declaration postfix-operate-declaration > infix-operate-declaration prefix-operate-declaration → operator prefix operator{} postfix-operate-declaration → Operator postfix operator{} infix-operator-declaration → operatorInfixOperator {infix-operator-attributesopt} Infib-operate-attributes → precedence-clauseoptassociativity-clauseopt precedence-clause → precedenceprecedence-level Precedence – level – Digit 0 through 255 associativity – clause – associativityassociativity associativity and left right none
Data Collection Office
Due to the limited space of the article, I can only briefly introduce some current work achievements and thoughts, and there are some new directions to explore in each Swift. If you are interested in the underlying principles, architecture design, system construction and how to interview of iOS, you can also follow me to get the latest information and information related to the interview. If you have any comments and suggestions, welcome to leave me a message!
The bad place that writes welcomes everybody to point out, hope everybody leaves a message to discuss more, let us progress together!
Those who like iOS can pay attention to me and study together!!
Link: www.jianshu.com/p/6638bbb73…