使用 Swift 中的 SWXMLHash 反序列化 class 3

Deserialising a class with SWXMLHash in Swift 3

我正在尝试使用自述文件末尾提供的示例将 XML 反序列化为 class,但它引发了与最初引发的相同的编译时错误 .

method 'deserialize' in non-final class 'Element' must return Self to conform to protocol 'XMLElementDeserializable'

我已尝试尽可能逐字逐句地使用该示例(尽管随着结构 Date 的变化很大,现在主要用于 NSDate),但我仍然遇到同样的问题。

这是我正在尝试使用的代码(本质上相同,只是为了清楚起见进行了删减

import Foundation
import SWXMLHash

class Element: XMLElementDeserializable {

    public static func deserialize(element: SWXMLHash.XMLElement) throws -> Self {
        return value(Element())
    }

    private static func value<T>(_ element: Element) -> T {
        return element as! T
    }

}

deserialize 实现没有实现蓝图

您自己的 deserialize 函数未实现 XMLElementDeserializable 中的蓝图,这意味着 deserialize(来自 XMLElementDeserializable)的默认实现将可用于您的 class Element。这个默认实现是一个抛出错误的实现,这是你有点混淆的错误消息的来源。

来自the source code of the SWXMLHash framework

/// Provides XMLElement deserialization / type transformation support
public protocol XMLElementDeserializable {
    /// Method for deserializing elements from XMLElement
    static func deserialize(_ element: XMLElement) throws -> Self
                         /* ^^^^^^^^^- take note of the omitted external name
                                       in this signature */
}

/// Provides XMLElement deserialization / type transformation support
public extension XMLElementDeserializable {
    /**
    A default implementation that will throw an error if it is called
    - parameters:
        - element: the XMLElement to be deserialized
    - throws: an XMLDeserializationError.ImplementationIsMissing if no implementation is found
    - returns: this won't ever return because of the error being thrown
    */
    static func deserialize(_ element: XMLElement) throws -> Self {
        throw XMLDeserializationError.ImplementationIsMissing(
            method: "XMLElementDeserializable.deserialize(element: XMLElement)")
    }
}

请注意您的 deserialize 方法的签名与蓝图之间的不匹配:后者明确省略了其外部参数名称 (_),而您的则没有。

用最小的例子分析错误情况

我们可以构造一个类似的最小示例来实现相同的错误消息。

enum FooError : Error {
    case error
}

protocol Foo {
    static func bar(_ baz: Int) throws -> Self
}

extension Foo {
    static func bar(_ baz: Int) throws -> Self {
        throw FooError.error
    }
}

// Bar implements its own bar(baz:) method, one which does
// NOT implement bar(_:) from the protocol Foo. This means
// that the throwing erroneous default implementation of 
// bar(_:) becomes available to Bar, yielding the same error
// message as in your question
class Bar : Foo {
    // does not match the blueprint!
    static func bar(baz: Int) throws -> Self {
        return value(Bar())
    }

    private static func value<T>(_ bar: Bar) -> T {
        return bar as! T
    }
}

     // Error!

这会产生以下错误消息:

error: method 'bar' in non-final class 'Bar' must return Self to conform to protocol 'Foo'

 static func bar(_ baz: Int) throws -> Self { ...

如果我们修复 Barbar 方法的签名以匹配 Foo 中的蓝图签名,我们将不再提示错误

/* ... FooError and Foo as above */

// Bar implements bar(_:) from protocol Foo, which
// means the throwing erroneous default implementation
// of bar(_:) is never in effect, OK
class Bar : Foo {
    static func bar(_ baz: Int) throws -> Self {
        return value(Bar())
    }

    private static func value<T>(_ bar: Bar) -> T {
        return bar as! T
    }
}

为了避免类型推断修复(将 Bar() 推断为有效的 Self 实例),将 Bar 标记为 final 并显式注释 Self[= 的类型46=]

/* ... FooError and Foo as above */

final class Bar : Foo {
    static func bar(_ baz: Int) throws -> Bar {
        return Bar()
    }
}

适用于您的用例

考虑到以上情况,您需要将您的deserialize签名修改为

public static func deserialize(_ element: SWXMLHash.XMLElement) throws -> Self { /* ... */ }

或者,如果您不打算子 classing Element class 本身,将其标记为 final 允许注释具体 return输入 Element 而不是 Self:

final class Element: XMLElementDeserializable {
    public static func deserialize(_ element: SWXMLHash.XMLElement) throws -> Element { /* ... */ }
}

(请注意,您当前的 deserialized 实现没有多大意义,因为它没有使用要反序列化的对象(内部参数名称 element) ,但是既然你提到你的例子被精简了,我会假设这是为了这个例子)。