prosource

일반 함수를 명시적으로 전문화할 수 없습니다.

probook 2023. 9. 10. 12:21
반응형

일반 함수를 명시적으로 전문화할 수 없습니다.

다음 코드에 문제가 있습니다.

func generic1<T>(name : String){
}

func generic2<T>(name : String){
     generic1<T>(name)
}

컴파일러 오류 "일반 함수를 명시적으로 전문화할 수 없음"으로 인한 generic1(이름) 결과

이 오류를 피할 수 있는 방법이 있습니까?generic1 function의 서명을 변경할 수 없으므로 (String) -> Void가 되어야 합니다.

저도 이 문제가 있어서 제 경우에 대한 해결책을 찾았습니다.

이 기사에서 저자는 같은 문제를 가지고 있습니다.

https://www.iphonelife.com/blog/31369/swift-programming-101-generics-practical-guide

그래서 문제는 컴파일러가 어떻게든 T의 종류를 추론해야 한다는 것입니다.그러나 단순히 generic< type >(params...)을 사용하는 것은 허용되지 않습니다.

일반적으로 컴파일러는 많은 경우 T가 사용되기 때문에 매개 변수 유형을 스캔하여 T의 유형을 찾을 수 있습니다.

저의 경우는 조금 달랐습니다. 왜냐하면 제 함수의 리턴 타입이 T였기 때문입니다.당신의 경우에는 당신의 기능에 T를 전혀 사용하지 않은 것 같습니다.예제 코드를 단순화한 것 같습니다.

그래서 다음과 같은 기능이 있습니다.

func getProperty<T>( propertyID : String ) -> T

예를 들어, 만약의 경우에는

getProperty<Int>("countProperty")

컴파일러가 제게 다음과 같은 오류를 줍니다.

일반 함수를 명시적으로 전문화할 수 없습니다.

따라서 컴파일러에게 T의 종류를 추론할 수 있는 또 다른 정보원을 제공하기 위해서는 반환값이 저장되는 변수의 종류를 명시적으로 선언해야 합니다.

var value : Int = getProperty("countProperty")

이렇게 하면 컴파일러는 T가 정수여야 한다는 것을 알 수 있습니다.

따라서 전반적으로 단순히 일반 함수를 지정하면 매개 변수 유형이나 반환 유형에서 T를 적어도 사용해야 한다는 것을 의미한다고 생각합니다.

스위프트 5

일반적으로 일반 함수를 정의하는 데는 여러 가지 방법이 있습니다.하지만 그들은 다음과 같은 조건에 근거를 두고 있습니다.T로 사용되어야 합니다.parameter, 또는 로서return type.

extension UIViewController {
    class func doSomething<T: UIView>() -> T {
        return T()
    }

    class func doSomethingElse<T: UIView>(value: T) {
        // Note: value is a instance of T
    }

    class func doLastThing<T: UIView>(value: T.Type) {
        // Note: value is a MetaType of T
    }
}

후에 는 는, 해야 합니다.T전화할 때에

let result = UIViewController.doSomething() as UIImageView // Define `T` by casting, as UIImageView
let result: UILabel = UIViewController.doSomething() // Define `T` with property type, as UILabel
UIViewController.doSomethingElse(value: UIButton()) // Define `T` with parameter type, as UIButton
UIViewController.doLastThing(value: UITextView.self) // Define `T` with parameter type, as UITextView

참조:

  1. http://austinzheng.com/2015/01/02/swift-generics-pt-1/
  2. https://dispatchswift.com/type-constraints-for-generics-in-swift-d6bf2f0dbbb2

솔루션이 클래스 유형을 매개 변수로 사용하고 있습니다(Java에서와 같이).

컴파일러가 어떤 유형을 다루고 있는지 알려주기 위해 인수로 클래스를 통과합니다.

extension UIViewController {
    func navigate<ControllerType: UIViewController>(_ dump: ControllerType.Type, id: String, before: ((ControllerType) -> Void)?){
        let controller = self.storyboard?.instantiateViewController(withIdentifier: id) as! ControllerType
        before?(controller)
        self.navigationController?.pushViewController(controller, animated: true)
    }
}

전화번호:

self.navigate(UserDetailsViewController.self, id: "UserDetailsViewController", before: {
        controller in
        controller.user = self.notification.sender
    })

정적 유형(String as parameter)이 있으므로 여기서는 일반 함수가 필요 없지만, 일반 함수를 호출하려면 다음을 수행할 수 있습니다.

일반 메소드 사용

func fetchObjectOrCreate<T: NSManagedObject>(type: T.Type) -> T {
    if let existing = fetchExisting(type) {
       return existing
    }
    else {
        return createNew(type)
    }
}

func fetchExisting<T: NSManagedObject>(type: T.Type) -> T {
    let entityName = NSStringFromClass(type)
     // Run query for entiry
} 

func createNew<T: NSManagedObject>(type: T.Type) -> T {
     let entityName = NSStringFromClass(type)
     // create entity with name
} 

generic 클래스 사용(generic과 같이 덜 유연한 경우 인스턴스당 1개 유형에 대해서만 정의할 수 있음)

class Foo<T> {

   func doStuff(text: String) -> T {
      return doOtherStuff(text)
   }

   func doOtherStuff(text: String) -> T {

   }  

}

let foo = Foo<Int>()
foo.doStuff("text")

제네릭 함수를 지정할 때는 다음과 같이 T 타입의 파라미터 중 일부를 지정해야 한다고 생각합니다.

func generic1<T>(parameter: T) {
    println("OK")
}

func generic2<T>(parameter: T) {
    generic1(parameter)
}

그리고 handle() 메서드를 호출하려면 프로토콜을 작성하고 T에 대한 유형 제약 조건을 지정하여 이 작업을 수행할 수 있습니다.

protocol Example {
    func handle() -> String
}

extension String: Example {
    func handle() -> String {
        return "OK"
    }
}

func generic1<T: Example>(parameter: T) {
    println(parameter.handle())
}

func generic2<T: Example>(parameter: T) {
    generic1(parameter)
}

따라서 String을 사용하여 다음과 같은 일반 함수를 부를 수 있습니다.

generic2("Some")

그리고 그것은 컴파일 할 것입니다.

지금까지 저의 개인적인 베스트 프랙티스는 @orkhan-alikhanov의 답변을 사용했습니다.오늘은 스위프트를 볼 때.UI 및 방법.modifier()그리고.ViewModifier구현된 경우, 다른 방법을 찾았습니다. (아니면 해결 방법이 더 있습니까?)

두 번째 함수를 간단히 a로 감습니다.struct.

예:

만약 이것이 당신에게 "일반적인 함수를 명시적으로 전문화할 수 없습니다"

func generic2<T>(name: String){
     generic1<T>(name)
}

이게 도움이 될 겁니다.선언을 마칩니다.generic1struct:

struct Generic1Struct<T> {
    func generic1(name: String) {## do, whatever it needs with T ##}
}

다음과 같이 부르시기 바랍니다.

func generic2<T>(name : String){
     Generic1Struct<T>().generic1(name: name)
}

비고:

  • 이 오류 메시지가 발생했을 때 어떤 경우에도 도움이 되는지 모르겠습니다.저는 이 일이 일어났을 때 여러 번 갇혀 있었다는 것을 알고 있습니다.이 솔루션이 오류 메시지가 나타난 오늘 도움이 되었다는 것을 알고 있습니다.
  • 스위프트가 제네릭을 다루는 방식은 여전히 저에게 혼란스럽습니다.
  • 이 예제 및 에 대한 해결 방법struct좋은 예입니다.여기서의 해결 방법은 조금 더 많은 정보는 없지만 컴파일러를 통과합니다.같은 정보인데 다른 결과?그러면 뭔가 잘못된 거죠.컴파일러 버그라면 수정할 수 있습니다.
func generic1<T>(of type: T.Type, name: String) {
    switch type {
    case is String.Type:
        print("String generic")
    case is Int.Type:
        print("Int generic")
    default:
        print("\(type) generic")
    }
    print(name)
}

func generic2<T>(of type: T.Type, name: String) {
     generic1(of: T.self, name: name)
}

generic2(of: String.self, name: "hello")
// String generic
// hello
generic2(of: Int.self, name: "world")
// Int generic
// world
generic2(of: Float.self, name: "bye")
// Float generic
// bye

로 전화한 이후로generic<T>()스위프트에서는 불법입니다
이것.generic(of: T.self)사용법은 제가 찾은 해결책입니다.

일반 클래스 기능에 비슷한 문제가 있었습니다.class func retrieveByKey<T: GrandLite>(key: String) -> T?.

나는 그것을 부를 수 없었습니다.let a = retrieveByKey<Categories>(key: "abc")여기서 Categories는 GrandLite의 하위 클래스입니다.

let a = Categories.retrieveByKey(key:"abc")범주가 아닌 GrandLite가 돌아왔습니다.일반 함수는 자신을 호출하는 클래스에 따라 유형을 추론하지 않습니다.

class func retrieveByKey<T: GrandLite>(aType: T, key: String>) -> T?제가 시도했을 때 오류를 냈습니다.let a = Categories.retrieveByKey(aType: Categories, key: "abc")Categories를 변환할 수 없다는 오류를 주었습니다.범주가 GrandLite의 하위 클래스임에도 불구하고 GrandLite에 입력합니다.하지만..

class func retrieveByKey<T: GrandLite>(aType: [T], key: String) -> T? 내가 노력하면 일을 했습니다.let a = Categories.retrieveByKey(aType: [Categories](), key: "abc")subclass의 명시적인 할당은 작동하지 않지만 다른 일반적인 유형(array)을 사용하는 암시적인 할당은 Swift 3에서 작동합니다.

언급URL : https://stackoverflow.com/questions/27965439/cannot-explicitly-specialize-a-generic-function

반응형