Swift 프로토콜에서 선택적 방법을 정의하는 방법은 무엇입니까?
스위프트에서 가능합니까? 그렇지 않은 경우 해결 방법이 있습니까?
1. 기본 구현 사용 (권장).
protocol MyProtocol {
func doSomething()
}
extension MyProtocol {
func doSomething() {
/* return a default value or just leave empty */
}
}
struct MyStruct: MyProtocol {
/* no compile error */
}
장점
Objective-C 런타임이 필요하지 않습니다 (적어도 명시 적으로는 아님). 즉, 구조체, 열거 형 및 비
NSObject클래스를 준수 할 수 있습니다 . 또한 강력한 제네릭 시스템을 활용할 수 있습니다.이러한 프로토콜을 준수하는 유형을 만날 때 항상 모든 요구 사항이 충족되는지 확인할 수 있습니다 . 항상 구체적인 구현이거나 기본 구현입니다. "인터페이스"또는 "계약"이 다른 언어로 작동하는 방식입니다.
단점
Void요구 사항이 아닌 경우 적절한 기본값을 가져야 하지만 항상 가능하지는 않습니다. 그러나이 문제점이 발생하면 해당 요구 사항에 실제로 기본 구현이 없거나 API 설계 중에 실수를 한 것입니다.적어도 특별한 반환 값으로 그 문제를 해결하지 않고 는 기본 구현과 구현하지 않음을 구별 할 수 없습니다 . 다음 예제를 고려하십시오.
protocol SomeParserDelegate { func validate(value: Any) -> Bool }방금 반환하는 기본 구현을 제공하면
true언뜻보기에 괜찮습니다. 이제 다음 의사 코드를 고려하십시오.final class SomeParser { func parse(data: Data) -> [Any] { if /* delegate.validate(value:) is not implemented */ { /* parse very fast without validating */ } else { /* parse and validate every value */ } } }이러한 최적화를 구현할 수있는 방법은 없습니다. 대리인이 메소드를 구현하는지 여부를 알 수 없습니다.
이 문제를 극복 할 수있는 여러 가지 방법이 있지만 (선택적 클로저, 서로 다른 작업에 대한 다른 대리자 개체를 사용하여) 몇 가지 방법으로 문제를 명확하게 보여줍니다.
사용 @objc optional.
@objc protocol MyProtocol {
@objc optional func doSomething()
}
class MyClass: NSObject, MyProtocol {
/* no compile error */
}
장점
- 기본 구현이 필요하지 않습니다. 선택적인 메소드 나 변수를 선언하면 준비가 완료됩니다.
단점
모든 준수 유형이 Objective-C와 호환되도록 요구 하여 프로토콜의 기능 을 심각하게 제한합니다 . 즉, 상속받은 클래스 만
NSObject이러한 프로토콜을 준수 할 수 있습니다. 구조체, 열거 형, 관련 형식이 없습니다.선택적으로 적합한 유형을 구현하는지 여부를 선택적으로 호출하거나 확인 하여 선택적 방법이 구현되었는지 항상 확인해야 합니다. 선택적 메소드를 자주 호출하는 경우 많은 상용구가 발생할 수 있습니다.
Swift 2 이상에서는 프로토콜의 기본 구현을 추가 할 수 있습니다. 이것은 프로토콜에서 새로운 선택적인 방법을 만듭니다.
protocol MyProtocol {
func doSomethingNonOptionalMethod()
func doSomethingOptionalMethod()
}
extension MyProtocol {
func doSomethingOptionalMethod(){
// leaving this empty
}
}
선택적 프로토콜 메소드를 작성하는 것은 좋은 방법은 아니지만 프로토콜 콜백에서 구조체를 사용할 수 있습니다.
나는 여기에 작은 요약을 썼다 : https://www.avanderlee.com/swift-2-0/optional-protocol-methods/
선택적 수정 자 및 @objc 속성 을 사용하여 선택적 요구 사항 프로토콜을 정의 하는 방법에 대한 답변 이 있으므로 프로토콜 확장을 사용하여 선택적 프로토콜을 정의하는 방법에 대한 샘플을 제공합니다.
아래 코드는 Swift 3. *입니다.
/// Protocol has empty default implementation of the following methods making them optional to implement:
/// `cancel()`
protocol Cancelable {
/// default implementation is empty.
func cancel()
}
extension Cancelable {
func cancel() {}
}
class Plane: Cancelable {
//Since cancel() have default implementation, that is optional to class Plane
}
let plane = Plane()
plane.cancel()
// Print out *United Airlines can't cancelable*
프로토콜 확장 메소드는 Objective-C 코드로 호출 할 수 없으며 Swift 팀은이를 수정하지 않습니다. https://bugs.swift.org/browse/SR-492
다음은 위임 패턴이있는 구체적인 예입니다.
프로토콜 설정 :
@objc protocol MyProtocol:class
{
func requiredMethod()
optional func optionalMethod()
}
class MyClass: NSObject
{
weak var delegate:MyProtocol?
func callDelegate()
{
delegate?.requiredMethod()
delegate?.optionalMethod?()
}
}
델리게이트를 클래스로 설정하고 프로토콜을 구현하십시오. 선택적 메소드를 구현할 필요가 없음을 참조하십시오.
class AnotherClass: NSObject, MyProtocol
{
init()
{
super.init()
let myInstance = MyClass()
myInstance.delegate = self
}
func requiredMethod()
{
}
}
한 가지 중요한 점은 선택적 방법이 선택적이며 "?"가 필요하다는 것입니다. 전화 할 때. 두 번째 물음표를 언급하십시오.
delegate?.optionalMethod?()
신속한 특정 유형을 사용하는 경우 프로토콜을 "@objc"로 표시하는 것과 관련된 다른 답변은 작동하지 않습니다.
struct Info {
var height: Int
var weight: Int
}
@objc protocol Health {
func isInfoHealthy(info: Info) -> Bool
}
//Error "Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C"
신속하게 작동하는 선택적 프로토콜을 선언하려면 함수를 func 대신 변수로 선언하십시오.
protocol Health {
var isInfoHealthy: (Info) -> (Bool)? { get set }
}
그런 다음 다음과 같이 프로토콜을 구현하십시오.
class Human: Health {
var isInfoHealthy: (Info) -> (Bool)? = { info in
if info.weight < 200 && info.height > 72 {
return true
}
return false
}
//Or leave out the implementation and declare it as:
//var isInfoHealthy: (Info) -> (Bool)?
}
그런 다음 "?"를 사용할 수 있습니다. 기능 구현 여부 확인
func returnEntity() -> Health {
return Human()
}
var anEntity: Health = returnEntity()
var isHealthy = anEntity.isInfoHealthy(Info(height: 75, weight: 150))?
//"isHealthy" is true
에서 스위프트 3.0
@objc protocol CounterDataSource {
@objc optional func increment(forCount count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
}
시간을 절약 할 수 있습니다.
optional각 방법 전에 키워드 를 추가해야합니다 .- 그러나 이것이 작동 하려면 프로토콜에 @objc 속성이 표시되어 있어야합니다.
- 이것은이 프로토콜이 클래스에는 적용 가능하지만 구조에는 적용되지 않음을 의미합니다.
Antoine의 답변의 메커니즘을 설명하려면 :
protocol SomeProtocol {
func aMethod()
}
extension SomeProtocol {
func aMethod() {
print("extensionImplementation")
}
}
class protocolImplementingObject: SomeProtocol {
}
class protocolImplementingMethodOverridingObject: SomeProtocol {
func aMethod() {
print("classImplementation")
}
}
let noOverride = protocolImplementingObject()
let override = protocolImplementingMethodOverridingObject()
noOverride.aMethod() //prints "extensionImplementation"
override.aMethod() //prints "classImplementation"
프로토콜 상속을 통한 순수한 Swift 접근 방식 :
//Required methods
protocol MyProtocol {
func foo()
}
//Optional methods
protocol MyExtendedProtocol: MyProtocol {
func bar()
}
class MyClass {
var delegate: MyProtocol
func myMethod() {
(delegate as? MyExtendedProtocol).bar()
}
}
선택적 프로토콜 메소드를 구현할 수있는 방법 을 묻기 전에 왜 구현해야하는지 묻어 야한다고 생각합니다.
우리가 빠른 프로토콜을 고전적인 객체 지향 프로그래밍에서 인터페이스 로 생각한다면 , 선택적 메소드는 그다지 의미가 없으며 아마도 기본 구현을 만들거나 프로토콜을 프로토콜 세트로 분리하는 것이 더 나은 해결책 일 것입니다 (아마도 상속 관계가있는 경우) 프로토콜에서 가능한 방법 조합을 나타냅니다.
자세한 내용은 https://useyourloaf.com/blog/swift-optional-protocol-methods/를 참조 하십시오 .이 문제에 대한 훌륭한 개요를 제공합니다.
원래 질문에서 약간 벗어난 주제이지만 Antoine의 아이디어를 바탕으로 누군가에게 도움이 될 것이라고 생각했습니다.
프로토콜 확장이있는 구조체에 대해 계산 된 속성을 선택적으로 만들 수도 있습니다.
프로토콜의 속성을 선택적으로 만들 수 있습니다
protocol SomeProtocol {
var required: String { get }
var optional: String? { get }
}
프로토콜 확장에서 더미 계산 속성 구현
extension SomeProtocol {
var optional: String? { return nil }
}
그리고 이제 선택적 속성이 구현되었거나 구현되지 않은 구조체를 사용할 수 있습니다
struct ConformsWithoutOptional {
let required: String
}
struct ConformsWithOptional {
let required: String
let optional: String?
}
또한 내 블로그의 Swift 프로토콜에서 선택적 속성 을 수행하는 방법을 작성했습니다 . Swift 2 릴리스를 통해 변경 사항이있는 경우 계속 업데이트하겠습니다.
선택적이고 필요한 델리게이트 메소드를 작성하는 방법
@objc protocol InterViewDelegate:class {
@objc optional func optfunc() // This is optional
func requiredfunc()// This is required
}
다음은 신속한 클래스에만 해당하는 간단한 예제이며 구조 또는 열거 형에는 해당되지 않습니다. 선택적인 프로토콜 방법에는 두 가지 수준의 옵션 연결이 있습니다. 또한 프로토콜을 채택한 클래스는 선언에 @objc 속성이 필요합니다.
@objc protocol CollectionOfDataDelegate{
optional func indexDidChange(index: Int)
}
@objc class RootView: CollectionOfDataDelegate{
var data = CollectionOfData()
init(){
data.delegate = self
data.indexIsNow()
}
func indexDidChange(index: Int) {
println("The index is currently: \(index)")
}
}
class CollectionOfData{
var index : Int?
weak var delegate : CollectionOfDataDelegate?
func indexIsNow(){
index = 23
delegate?.indexDidChange?(index!)
}
}
순식간에 신속하게하고 싶다면 가장 좋은 방법은 Swift 유형의 구조체 와 같은 Swift 유형을 반환하는 경우 기본 구현 particullary를 제공하는 것입니다
예 :
struct magicDatas {
var damagePoints : Int?
var manaPoints : Int?
}
protocol magicCastDelegate {
func castFire() -> magicDatas
func castIce() -> magicDatas
}
extension magicCastDelegate {
func castFire() -> magicDatas {
return magicDatas()
}
func castIce() -> magicDatas {
return magicDatas()
}
}
모든 기능 을 정의하지 않고 프로토콜을 구현할 수 있습니다.
하나의 옵션은 옵션 함수 변수로 저장하는 것입니다.
struct MyAwesomeStruct {
var myWonderfulFunction : Optional<(Int) -> Int> = nil
}
let squareCalculator =
MyAwesomeStruct(myWonderfulFunction: { input in return input * input })
let thisShouldBeFour = squareCalculator.myWonderfulFunction!(2)
Optional Protocol신속하게 정의하려면 해당 프로토콜 내에서 선언 및 / 선언 @objc전에 키워드 를 사용해야 합니다. 다음은 프로토콜의 선택적 속성 샘플입니다.Protocolattributemethod
@objc protocol Protocol {
@objc optional var name:String?
}
class MyClass: Protocol {
// No error
}
프로토콜에서 함수를 정의하고 해당 프로토콜의 확장을 만든 다음 선택적으로 사용할 함수에 대해 빈 구현을 만듭니다.
@optional메서드 나 속성 앞에을 넣습니다 .
참고 URL : https://stackoverflow.com/questions/24032754/how-to-define-optional-methods-in-swift-protocol
'development' 카테고리의 다른 글
| 동일한 서버의 Apache 및 Node.js (0) | 2020.03.03 |
|---|---|
| 머큐리얼이 "잠금 대기 중"으로 멈춤 (0) | 2020.03.03 |
| IntelliJ에서 현재 파일 찾기 (0) | 2020.03.03 |
| 루비의 디렉토리에서 모든 파일을 요구하는 가장 좋은 방법은 무엇입니까? (0) | 2020.03.03 |
| 휘발성 키워드를 사용하는 이유는 무엇입니까? (0) | 2020.03.03 |