Swift Learning-24--Protocol 01

Source: Internet
Author: User
Tags instance method

A protocol defines a blueprint that specifies the methods, attributes, and other things needed to implement a particular task or function.

Classes, structs, or enumerations can follow the protocol and provide specific implementations for those requirements defined by the Protocol, and a type that satisfies the requirements of a protocol, it can be said that the type follows this protocol

In addition to complying with the requirements of the type of protocol that must be implemented, you can extend the protocol to implement some of the extensions or implement some additional functionality, so that the types of protocols you follow can use these features

Syntax of the Protocol

Protocols are defined in much the same way as classes, structs, and enumerations.

Protocol someprotocol{

Here is the definition part of the protocol.

// }

To have a custom type adhere to a protocol, when defining a type, you need to add a protocol name after the type name, with the middle (:) segmentation, when following multiple protocols, between the protocols with (,) split

struct somestruct:firstprotocol,anotherprotocol{

Here is the definition part of the struct

// }

Class with parent class in the training protocol, the class name of the parent class should be placed before the protocol name, split

Class someclass:somesuperclass.firstprotocol,anotherprotocol{

Here is the definition part of the class

// }

Property requirements

A protocol can require instance properties or type properties that follow a type of protocol to provide a specific name and type

The protocol does not specify whether a property is a stored or computed property, it specifies only the name and type of the property, and the protocol number specifies whether the property is readable or readable writable

If the protocol requires that the property be readable and writable, then the property cannot be a constant attribute or a read-only computed property, and if the protocol requires that the property be readable, then the property is not only readable if the code requires it. It can also be writable.

The protocol always uses the VAR keyword to declare a variable property, with the type name appended with {set Get} to indicate that the property is readable and writable, and the readable attribute is declared with the {get}

Protocol someprotocol{

var mustbesettable:int {Get Set}

var dosenotneedtobesettable:int {Get}

}

When you define a type attribute in an agreement, always use the static keyword as the prefix, and when the class type follows the protocol, you can use the CLASS keyword to declare the Type property in addition to the Static keyword:

Protocol anotherprotocol{

static Var sometypeproperty:int {Get Set}

}

As follows: This is a protocol that contains only one instance property requirement:

Protocol fullnamed{

var fullname:string {Get}

}

The Fullnamed protocol, in addition to the FullName attribute that is required to comply with the type of protocol provided, does not require any other requirements, and this protocol indicates that any type that follows fullnamed must have an instance property of type String for a tick fullName

Here is a simple struct that follows the Fullnamed protocol

struct person:fullnamed{

var fullname:string

}

Let John = Person.init (fullName: "John Appleseed")

This example defines a person's structure, which is used to denote a name, which follows the fullnamed protocol.

Each instance of the person struct has a type of String storage property, FullName, which satisfies the requirements of the Fullnamed protocol, assuming that the person struct correctly conforms to the Protocol (if the protocol requirements are not fully met, the compile-time error )

Here's a more complicated example.

Class starship:fullnamed{

var prefix:string?

var name:string

Init (name:string,prefix:string?) {

Self.name = Name

Self.prefix = Prefix

}

var fullname:string{

return (prefix! = nil? prefix! + "": "") + Name

}

}

var ncc1701 = starship.init (name: "Enterprise", Prefix: "USS")

Method requirements

A protocol can require that certain specified instance methods or class methods be implemented in accordance with the type of the protocol, as part of the protocol, in the definition of the protocol as a normal method, but without braces and method bodies, which can be defined in the protocol with variable parameters, as in normal methods, but Providing default values for the parameters of the methods in the protocol is not supported

As described in the attribute requirements, when defining a class method in a protocol, always use the static keyword as a prefix, and when the class type follows Rey, you can use the Class keyword as a prefix, in addition to the static keyword.

The following example defines a protocol that contains only one instance method:

Protocol randomnumbergenerator{

Func random () Double

}

The RandomNumberGenerator protocol requires that a type that follows the protocol must have an instance method named random that returns a value of type Double. Although not specified here, we assume that the return value is within the [0.0,1.0] range

The RandomNumberGenerator protocol does not care how each random number is generated, it only requires a random number to be supplied to the living device

As shown below:

Class linearcongrentialgenerator:randomnumbergenerator{

var lastrandom = 42.0

Let M = 139968.0

Let A = 3877.0

Let C = 29573.0

Func random ()-Double {

Lastrandom = ((Lastrandom * a + C). Truncatingremainder (DIVIDINGBY:M))

Return lastrandom/m

}

}

Let generator = Linearcongrentialgenerator.init ()

Print ("Here ' s a random number: \ (Generator.random ())")

Print ("and another one: \ (Generator.random ())")

Mutating method Requirements

Sometimes it is necessary to change the instance of a method in a method, for example, in an instance method of a value type (that is, struct and enum), the mutating keyword is prefixed with the method, written in front of the Func, indicating that the instance to which it belongs and the value of any property of the instance can be modified in the method.

If you define an instance method in the agreement, the method changes the instance of the type following the protocol, then the definition protocol is required to add the mutating keyword before the method, which allows the struct and enumeration to follow the protocol and satisfy this method requirement

Note: When implementing the Mutating method in the protocol, if the class type does not have to write the mutating keyword, and for structs and enumerations, you must write the Mutataing keyword

Protocol togglable{

mutating func Toggle ()

}

The toggle () method, when defined, uses the Mutating keyword tag, which indicates that when it is called, the method will change the instance of the type following the protocol.

When using enumerations or structs to implement the Togglable protocol, you need to provide a toggle () method with a mutating prefix

Enum oneoffswitch:togglable{

Case off, on

mutating func Toggle () {

Switch Self {

case. Off:

Self =. On

Case-On:

Self =. Off

}

}

}

var lightSwitch = Oneoffswitch.off

Lightswitch.toggle ()

Constructor requirements

The protocol can require that the specified constructor be implemented in accordance with the type of the protocol, and you can write the constructor's declaration in the definition of the protocol, without writing the braces and the constructor's entity, as you would write the generic constructor.

Protocol someprotocol2{

Init (Someparameter:int)

}

Constructors require implementations in a class

You can implement constructors in classes that follow the protocol, either as a constructor or as a convenience constructor, and in either case you must label the constructor implementation with the required modifier

Class someclass:someprotocol2{

Required Init (someparameter:int) {

Here is the implementation part of the constructor

}

}

Using the required modifier ensures that all subclasses must provide this constructor implementation, which can also compound the protocol

If the class has already been marked as final, then the implementation value of the constructor that does not need to be negotiated uses the required modifier, because the final class cannot have subclasses

If a subclass overrides the specified constructor of the parent class, and the constructor satisfies the requirements of a protocol, the implementation of the constructor requires that both the required and the override modifiers be annotated

Protocol SomeProtocol3 {

Init ()

}

Class SomeSuperClass3 {

Init () {

Here is the implementation part of the constructor

}

}

Class Somesubclass:somesuperclass3, SomeProtocol3 {

Because following the agreement, we need to add required

Because inheriting from the parent class, you need to add override

Required override Init () {

Here is the implementation part of the constructor

}

}

can fail constructor requirements

The protocol can also define a constructor requirement that can fail for a type that follows a protocol

Types that follow the protocol can meet the requirements of the failed constructors defined in the protocol through the Class table's constructor (init?) or the non-failed constructor (INIT)

Non-fail constructors that are defined in the protocol can fail the constructor (init!) through a non-fail constructor (init) or an implicit unpacking To meet

Protocol as type

Although the protocol itself does not implement any functionality, the protocol can be used as a mature type

Protocols can be used just like other types, using scenarios such as the following

As a function, a parameter type or a return value type in a method or struct body

As a constant, the type of the variable or property

As an array, an element type in a dictionary or other container

Note: The protocol is a type, so the name of the protocol type should be the same as other types (Int, Double, String), and camel-like notation, which begins with uppercase letters

Class Dice {

Let Sides:int

Let Generator:randomnumbergenerator

Init (Sides:int, Generator:randomnumbergenerator) {

Self.sides = Sides

Self.generator = Generator

}

Func roll (), Int {

Return Int (Generator.random () * Double (sides)) + 1

}

}

Delegate (proxy) mode

A delegate is a design pattern that allows a class or struct to delegate functionality to other types of instances that require them to be responsible, and the implementation of the delegate pattern is simple: Define the protocol to encapsulate the functions that need to be delegated, so that the types that follow the protocol can provide these functions, the delegate pattern can be used to respond to a specific action, or External data sources, without caring about the type of external data sources

Protocol dicegame{

var dice:dice{get}

Func Play ()

}

Protocol dicegamedelegate{

Func Gamedidstart (_ Game:dicegame)

Func Game (_ Game:dicegame, Didstartnewturnwithdiceroll diceroll:int)

Func Gamedidend (_ Game:dicegame)

}

The Dicegame protocol can be followed by any game involving dice, dicegamedelegate protocol can be followed by any type, used to track Dicegame's game process

as shown below.

Class sankesandladders:dicegame{

Let Finalsquare = 25

Let dice = Dice.init (Sides:6, Generator:linearcongrentialgenerator ())

var square = 0

VAR board: [Int]

Init () {

board = [Int].init (repeating:0, Count:finalsquare + 1)

BOARD[03] = +08; BOARD[06] = +11; BOARD[09] = +09; BOARD[10] = +02

BOARD[14] =-10; BOARD[19] =-11; BOARD[22] =-02; BOARD[24] = 08

}

var delegate:dicegamedelegate?

Func Play () {

Square = 0

Delegate?. Gamedidstart (self)

Gameloop:while Square! = finalsquare{

Let Diceroll = Dice.roll ()

Delegate?. Game (self, didstartnewturnwithdiceroll:diceroll)

Switch Square + diceroll {

Case Finalsquare:

Break Gameloop

Case let Newsquare where Newsquare > Finalsquare:

Continue Gameloop

Default

Square + = Diceroll

Square + = Board[square]

}

}

Delegate?. Gamedidend (self)

}

}

The following example defines the Dicegametracker class, which follows the Dicegamedelegate protocol:

Class dicegametracker:dicegamedelegate{

var numberofturns = 0

Func Gamedidstart (_ Game:dicegame) {

Numberofturns = 0

If game is sankesandladders {

Print ("Started a new game of Snaks and Ladders")

}

Print ("The game is using a \ (game.dice.sides)-sided dice")

}

Func Game (_ Game:dicegame, Didstartnewturnwithdiceroll diceroll:int) {

Numberofturns + = 1

Print ("Rolled a \ (diceroll)")

}

Func Gamedidend (_ Game:dicegame) {

Print ("The game lasted for \ (Numberofturns) turns")

}

}

Swift Learning-24--Protocol 01

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.