프로토콜에서 기본 인자를 사용할 때의 확장 쓰기 정리

15226 단어 iOSSwift초학자tech
iOS 애플리케이션으로 개인 개발을 진행하면서 스위프트와 디자인 모델을 배운다.
이번에는 프레젠터의 디자인을 배울 때 적극적으로 활용protocol했지만 이 과정에서 매개 변수에 기본값을 주고 싶은 장면이 나왔다.협의의 기재 방법을 충분히 이해하지 못했기 때문에 일반적인 제작 방법이 제공하는 매개 변수와 동일하여 다음과 같은 오류가 발생하였다.조금이나마 다시 이해하기까지 시간이 좀 걸렸기 때문에 이 테이블로 정리했다.
//① 
protocol TestProtocol {
        //Default argument not permitted in a protocol method
    func test(a: Int, b: Int = 15)  -> Int
}
잘못된 문장에 쓰인 바와 같이 프로토콜에서 직접 파라미터 값을 기본적으로 제공할 수 없습니다.그러나 줄 방법이 없는 것은 아니다. 결과는 기본 매개 변수 등의 작용을 할 수 있는 값이다.이를 위해 필요한 것은 extension 의 기본 실시 (이미 정해진 실시) 이다.

서법


처음에 확인한 바와 같이 프로토콜에서 기본 파라미터를 직접 사용할 수 없지만 확장에서의 실현을 통해 수치를 프로토콜 안에 전달하는 방법 등은 실질적으로 기본 파라미터로 사용할 수 있다.
//① 通常のプロトコル
protocol TestProtocol {
    func testA(a: Int, b: Int) -> (Int,Int)
}

extension TestProtocol {
    //② デフォルト実装(規定実装)
    func testB(a: Int, b: Int = 15) -> (Int,Int) {
	//①引数に②引数の値を代入するという処理
        testA(a: a, b: b) 
    }
}
주의해야 할 것은 ①와 ②는 기본적으로 다른 방법이다.확장이 기본적으로 프로토콜에 기재된 방법의 매개 변수가 아니라는 것을 나타내기 위해 ①를testA로 하고 ②를testB로 하지만 실제 이용에서는 A와 B를 구별할 필요가 없다.
테스트 B 방법에서 테스트 A라고 하는데 테스트 B에서 기본적으로 설정된 파라미터의 값을 테스트 A에게 건네준다. 원래 기본 파라미터에 대한 프로토콜을 주지 말아야 하는 방법인 테스트 A는 마치 사용할 수 있는 것처럼 사용할 수 있다.
다른 방법인지 식별할 수 없기 때문에 확장을 사용하면 일반적인 방법의 매개 변수 이름에 기본값을 추가로 쓰기 때문에 오해를 풀기 전에 많은 시간이 걸렸다.

사용법


기본 실시는 이미 실시된 것으로 처리되기 때문에 협의에 부합되는 반과 구조체 내부에 그 방법 등을 쓸 필요가 없다.또는 쓰면 invalid의 정의로 튀어나온다.실제 코드로 사용 방법을 확인하다.여기에는 A와 B의 차이가 없다.
//①通常のプロトコル
protocol TestProtocol {
    func test(a: Int, b: Int) -> (Int,Int)
}

extension TestProtocol {
        //②デフォルト実装
    func test(a: Int, b: Int = 15)  -> (Int,Int) {
        test(a: a, b: b)
    }
}

//①プロトコルに適合させた構造体
struct TestStruct: TestProtocol {
    //①プロトコルのメソッドを準拠し、処理を記述
    //②デフォルト実装はプロトコルに適合させた時点で準拠されている
    func test(a: Int, b: Int) -> (Int,Int) {
        return (a,b)
    }
}

let testStruct = TestStruct()

//① 呼んでいるのはプロトコルのメソッド
let a = testStruct.test(a: 10, b: 20) 

//② 呼んでいるのはデフォルト実装のメソッド
//ここでは b = 15がデフォルトで与えられている
let b = testStruct.test(a: 10) 
딱 보면 알겠지만 협의에 부합되는 구조체에서 기본적으로 실현되는 방법을 기술할 필요가 없다.처리를 기술했기 때문에 협의에 부합할 때 호출할 수 있다.

기본 상황을 고려하여 명칭은 같다


기본값이라는 단어의 원래 뜻을 감안하여 확장을 통해 파라미터를 제공하는 방법의 이름을 얻으려면 프로토콜에 기재된 방법의 이름과 같으면 자연스러울 것입니다.결과적으로 처리된 내용은 프로토콜을 호출하는 방법일 뿐이다.
용법의 예를 들어 생각해 보아라.
//① 呼んでいるのはプロトコルのメソッド
let a = testStruct.test(a: 10, b: 20) 

//② 呼んでいるのはデフォルト実装のメソッド
//ここでは b = 15がデフォルトで与えられている
let b = testStruct.test(a: 10) 
구분하기 편리하도록 처음부터 테스트A, 테스트B와 방법명을 분리했지만 결과는 기본 매개 변수의 중계지점을 전달하기 위한 것이었다. 협의 방법의 처리를 고려하면 명칭을 구분하지 않는 것이 자연스럽다.매개 변수를 확인하면 기본값이 주어졌는지 알 수 있습니다.
또 엄밀히 말하면 이름이 같은지 여부에 따라 Xcode 내부 처리 방법이 다를 수 있다고 설명했다.솔직히 말해서, 나는 이 점을 모른다.

초보 주의


프로토콜에 기본값을 이용한 글이 적혀 있는데 이 경우 붕괴될 수 있다는 뜻이다.
https://medium.com/@georgetsifrikas/swift-protocols-with-default-values-b7278d3eef22
Important note Because protocol BazProtocol has already a default implementation from the extension if you use it in an object and forgot to implement function foo compiler won’t complaint, but extension function foo will call itself recursively until your code crashes with BAD_ACCESS.
상술한 내용을 읽기만 하면 붕괴가 발생하지만 코드에는 컴파일러가 컴파일러에 의해 실행되지 않는다고 쓰여 있다. 즉, 통과되고 실제로는 컴파일러 오류가 나오지 않는다는 것이다.다만, 플레이 그라운드에서 시도해보면 워닝이 표시됩니다.
실제 코드로 확인해 보세요.
확장 측에서 기본 설치를 실시하는 경우, 이 내부에서 프로토콜 측에서 써야 할 방법을 호출합니다.하지만 기사에 나온 문제처럼 합의문에 방법을 빠뜨리는 경우는 어떨까.
나는'#쓰기'항목의 코드를 쓰면 이렇게 될 것이라고 생각한다.
protocol TestProtocol {
    //コメントアウト
    //func test(a: Int, b: Int) 
}

extension TestProtocol {
    //② デフォルト実装(規定実装)
    func test(a: Int, b: Int = 15) {
	//Swift Compiler Warning
	//Function call causes an infinite recursion
        self.test(a: a, b: b) 
    }
}
경고와 같이 방법은 무한히 호출됩니다.단지 경고, 번역 자체가 통과, 좀 무서워...
그나저나 이 이름을 바꾸면 어떨까
protocol TestProtocol {
    //コメントアウト
    //func testA(a: Int, b: Int) 
}

extension TestProtocol {
    //② デフォルト実装(規定実装)
    func testB(a: Int, b: Int = 15) {
	//Swift Compiler Error
	//Cannot find 'testA' in scope
        self.testA(a: a, b: b) 
    }
}
흔히 볼 수 있는 컴파일 오류.그래서 엄밀히 말하면 같은 이름으로 묵인하면 전혀 다른 방법이 아닌 것 같다.

참고 자료


https://yamatooo.blog/entry/2021/07/30/083000
https://qiita.com/nakagawa1017/items/18ff5b040957cba8e7e5

좋은 웹페이지 즐겨찾기