스위프트 프로토콜
프로토콜은 특정 기능을 구현하는 데 필요한 방법과 속성을 지정합니다.
프로토콜의 요구 사항을 충족할 수 있는 모든 유형을 프로토콜을 준수한다고 합니다.
클래스, 구조 또는 열거형 유형은 모두 프로토콜을 따를 수 있으며 프로토콜에 의해 정의된 메서드와 기능을 완성하기 위한 특정 구현을 제공할 수 있습니다.
Grammar
프로토콜의 구문 형식은 다음과 같습니다.
protocol SomeProtocol { // 协议内容 }
클래스가 특정 프로토콜을 따르도록 하려면 유형 이름 뒤에 프로토콜 이름을 콜론으로 구분하여 추가해야 합니다. 중간에 일부로 유형 정의 중. 여러 프로토콜을 따르는 경우 쉼표로 구분하세요.
struct SomeStructure: FirstProtocol, AnotherProtocol { // 结构体内容 }
프로토콜을 준수하면서 클래스에 상위 클래스가 있는 경우 상위 클래스 이름을 프로토콜 이름 앞에 쉼표로 구분하여 배치해야 합니다.
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol { // 类的内容 }
속성 프로비전
프로토콜은 저장 속성인지 계산 속성인지 지정하지 않고 특정 인스턴스 속성이나 클래스 속성을 지정하는 데 사용됩니다. 또한 읽기 전용인지, 읽기 및 쓰기가 가능한지 지정해야 합니다.
프로토콜에서 var는 일반적으로 변수 속성을 선언하는 데 사용됩니다. 속성이 읽기 및 쓰기 가능함을 나타내기 위해 유형 선언 뒤에 { set get }이 추가됩니다.
protocol classa { var marks: Int { get set } var result: Bool { get } func attendance() -> String func markssecured() -> String } protocol classb: classa { var present: Bool { get set } var subject: String { get set } var stname: String { get set } } class classc: classb { var marks = 96 let result = true var present = false var subject = "Swift 协议" var stname = "Protocols" func attendance() -> String { return "The \(stname) has secured 99% attendance" } func markssecured() -> String { return "\(stname) has scored \(marks)" } } let studdet = classc() studdet.stname = "Swift" studdet.marks = 98 studdet.markssecured() print(studdet.marks) print(studdet.result) print(studdet.present) print(studdet.subject) print(studdet.stname)
위 프로그램의 실행 출력은 다음과 같습니다.
98 true false Swift 协议 Swift
Mutating 메소드에 대한 규정
때때로 메소드에서 인스턴스를 변경해야 하는 경우가 있습니다.
예를 들어 값 유형(구조체, 열거형)의 인스턴스 메소드에서 mutating 키워드는 함수의 접두어로 사용되며 func 앞에 작성되어 해당 인스턴스가 속한 인스턴스와 해당 인스턴스 속성의 값을 나타냅니다. 이 방법으로 수정할 수 있습니다.
protocol daysofaweek { mutating func show() } enum days: daysofaweek { case sun, mon, tue, wed, thurs, fri, sat mutating func show() { switch self { case sun: self = sun print("Sunday") case mon: self = mon print("Monday") case tue: self = tue print("Tuesday") case wed: self = wed print("Wednesday") case mon: self = thurs print("Thursday") case tue: self = fri print("Friday") case sat: self = sat print("Saturday") default: print("NO Such Day") } } } var res = days.wed res.show()
위 프로그램의 실행 출력은 다음과 같습니다.
Wednesday
Provisions for constructors
프로토콜은 추종자들이 지정된 생성자를 구현하도록 요구할 수 있습니다.
일반 생성자를 작성하는 것처럼 프로토콜 정의에 생성자의 선언을 작성할 수 있지만 중괄호와 생성자의 엔터티를 작성할 필요는 없습니다. 구문은 다음과 같습니다.
protocol SomeProtocol { init(someParameter: Int) }
Example
protocol tcpprotocol { init(aprot: Int) }
프로토콜 생성자 클래스에서 구현 지정
이 프로토콜을 따르는 클래스에서 생성자를 구현하고 이를 클래스의 지정 초기화 또는 편의 초기화로 지정할 수 있습니다. 두 경우 모두 생성자 구현을 "필수" 수정자로 표시해야 합니다.
class SomeClass: SomeProtocol { required init(someParameter: Int) { // 构造器实现 } } protocol tcpprotocol { init(aprot: Int) } class tcpClass: tcpprotocol { required init(aprot: Int) { } }
필수 수정자를 사용하면 이 프로토콜을 따르는 모든 하위 클래스도 명시적인 생성자 사양 또는 상속된 구현을 제공할 수 있습니다.
하위 클래스가 상위 클래스의 지정된 생성자를 재정의하고 생성자가 특정 프로토콜의 조항을 준수하는 경우 생성자의 구현은 필수 및 재정의 수정자로 표시되어야 합니다.
protocol tcpprotocol { init(no1: Int) } class mainClass { var no1: Int // 局部变量 init(no1: Int) { self.no1 = no1 // 初始化 } } class subClass: mainClass, tcpprotocol { var no2: Int init(no1: Int, no2 : Int) { self.no2 = no2 super.init(no1:no1) } // 因为遵循协议,需要加上"required"; 因为继承自父类,需要加上"override" required override convenience init(no1: Int) { self.init(no1:no1, no2:0) } } let res = mainClass(no1: 20) let show = subClass(no1: 30, no2: 50) print("res is: \(res.no1)") print("res is: \(show.no1)") print("res is: \(show.no2)")
위 프로그램 실행 결과는 다음과 같습니다.
res is: 20 res is: 30 res is: 50
프로토콜 유형
프로토콜 자체에는 아무런 기능이 구현되어 있지 않지만 프로토콜을 유형으로 사용할 수 있습니다.
프로토콜은 다른 일반적인 유형, 사용 시나리오처럼 사용될 수 있습니다.
매개변수 유형 또는 함수, 메소드 또는 생성자의 반환 값 유형으로
상수, 변수 또는 속성 유형으로
요소 유형으로 배열, 사전 또는 기타 컨테이너
인스턴스
protocol Generator { typealias members func next() -> members? } var items = [10,20,30].generate() while let x = items.next() { print(x) } for lists in [1,2,3].map( {i in i*5}) { print(lists) } print([100,200,300]) print([1,2,3].map({i in i*10}))
위 프로그램 실행의 출력 결과는 다음과 같습니다.
10 20 30 5 10 15 [100, 200, 300] [10, 20, 30]
확장에 프로토콜 멤버 추가
확장을 통해 기존 유형(클래스, 구조체, 열거형 등)을 확장할 수 있습니다.
확장 기능은 속성, 메서드, 아래 첨자 스크립트, 프로토콜 및 기타 멤버를 기존 유형에 추가할 수 있습니다.
protocol AgeClasificationProtocol { var age: Int { get } func agetype() -> String } class Person { let firstname: String let lastname: String var age: Int init(firstname: String, lastname: String) { self.firstname = firstname self.lastname = lastname self.age = 10 } } extension Person : AgeClasificationProtocol { func fullname() -> String { var c: String c = firstname + " " + lastname return c } func agetype() -> String { switch age { case 0...2: return "Baby" case 2...12: return "Child" case 13...19: return "Teenager" case let x where x > 65: return "Elderly" default: return "Normal" } } }
프로토콜 상속
프로토콜은 하나 이상의 다른 프로토콜을 상속할 수 있으며, 상속된 프로토콜을 기반으로 새로운 콘텐츠 요구 사항이 추가될 수 있습니다.
프로토콜의 상속 구문은 클래스 상속과 유사합니다. 여러 상속된 프로토콜은 쉼표로 구분됩니다.protocol InheritingProtocol: SomeProtocol, AnotherProtocol { // 协议定义 }
Instance
protocol Classa { var no1: Int { get set } func calc(sum: Int) } protocol Result { func print(target: Classa) } class Student2: Result { func print(target: Classa) { target.calc(1) } } class Classb: Result { func print(target: Classa) { target.calc(5) } } class Student: Classa { var no1: Int = 10 func calc(sum: Int) { no1 -= sum print("学生尝试 \(sum) 次通过") if no1 <= 0 { print("学生缺席考试") } } } class Player { var stmark: Result! init(stmark: Result) { self.stmark = stmark } func print(target: Classa) { stmark.print(target) } } var marks = Player(stmark: Student2()) var marksec = Student() marks.print(marksec) marks.print(marksec) marks.print(marksec) marks.stmark = Classb() marks.print(marksec) marks.print(marksec) marks.print(marksec)
위 프로그램 실행의 출력 결과는 다음과 같습니다.
学生尝试 1 次通过 学生尝试 1 次通过 学生尝试 1 次通过 学生尝试 5 次通过 学生尝试 5 次通过 学生缺席考试 学生尝试 5 次通过 学生缺席考试
Class -특정 프로토콜
프로토콜의 상속 목록에서 클래스 키워드를 추가하면 프로토콜을 클래스 유형에만 적용할 수 있습니다.
class 키워드는 프로토콜의 상속 목록에 가장 먼저 나타나야 하고, 다른 상속된 프로토콜이 그 뒤에 나타나야 합니다. 형식은 다음과 같습니다:
protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol { // 协议定义 }
Example
protocol TcpProtocol { init(no1: Int) } class MainClass { var no1: Int // 局部变量 init(no1: Int) { self.no1 = no1 // 初始化 } } class SubClass: MainClass, TcpProtocol { var no2: Int init(no1: Int, no2 : Int) { self.no2 = no2 super.init(no1:no1) } // 因为遵循协议,需要加上"required"; 因为继承自父类,需要加上"override" required override convenience init(no1: Int) { self.init(no1:no1, no2:0) } } let res = MainClass(no1: 20) let show = SubClass(no1: 30, no2: 50) print("res is: \(res.no1)") print("res is: \(show.no1)") print("res is: \(show.no2)")
위 프로그램 실행 출력은 다음과 같습니다:
res is: 20 res is: 30 res is: 50
프로토콜 합성
Swift는 여러 프로토콜의 합성을 지원하며, 이는 여러 프로토콜을 동시에 따라야 할 때 매우 유용합니다. 시간.
구문 형식은 다음과 같습니다.
protocol<SomeProtocol, AnotherProtocol>
예제
protocol Stname { var name: String { get } } protocol Stage { var age: Int { get } } struct Person: Stname, Stage { var name: String var age: Int } func show(celebrator: protocol<Stname, Stage>) { print("\(celebrator.name) is \(celebrator.age) years old") } let studname = Person(name: "Priya", age: 21) print(studname) let stud = Person(name: "Rehan", age: 29) print(stud) let student = Person(name: "Roshan", age: 19) print(student)
위 프로그램의 실행 출력은 다음과 같습니다.
Person(name: "Priya", age: 21) Person(name: "Rehan", age: 29) Person(name: "Roshan", age: 19)
프로토콜의 일관성을 확인하세요
is 및 as 연산자를 사용하여 특정 프로토콜을 따르거나 특정 유형으로 강제 변환합니다.
is
연산자는 인스턴스가 특정프로토콜
을준수
하는지 확인하는 데 사용됩니다.is
操作符用来检查实例是否遵循
了某个协议
。as?
返回一个可选值,当实例遵循
协议时,返回该协议类型;否则返回nil
。as
as?
인스턴스가 프로토콜을 따르면
프로토콜 유형이 반환되고, 그렇지 않으면 nil
이 반환됩니다. . as
는 강제 하향 변환에 사용됩니다. 강제 변환이 실패하면 런타임 오류가 발생합니다. protocol HasArea { var area: Double { get } } // 定义了Circle类,都遵循了HasArea协议 class Circle: HasArea { let pi = 3.1415927 var radius: Double var area: Double { return pi * radius * radius } init(radius: Double) { self.radius = radius } } // 定义了Country类,都遵循了HasArea协议 class Country: HasArea { var area: Double init(area: Double) { self.area = area } } // Animal是一个没有实现HasArea协议的类 class Animal { var legs: Int init(legs: Int) { self.legs = legs } } let objects: [AnyObject] = [ Circle(radius: 2.0), Country(area: 243_610), Animal(legs: 4) ] for object in objects { // 对迭代出的每一个元素进行检查,看它是否遵循了HasArea协议 if let objectWithArea = object as? HasArea { print("面积为 \(objectWithArea.area)") } else { print("没有面积") } }🎜위 프로그램 실행의 출력 결과는 다음과 같습니다. 🎜
面积为 12.5663708 面积为 243610.0 没有面积🎜