我正试图使用自述文件末尾提供的示例将XML反序列化为一个类,但它引发的编译时错误与最初引发的this question相同。
非最终类“Element”中的“deserialize”方法必须返回Self才能符合协议“xmllementdeserializable”
我试图尽可能逐字地使用这个示例(虽然现在主要在NSDate上使用的是Date,一个struct,它的变化相当大),但是我仍然遇到了同样的问题。
这是我正在尝试使用的代码(本质上是相同的,只是为了清楚起见被删去了

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打印的一个blueprinted,这意味着deserialize(fromXMLElementDeserializable)的默认实现将对您的类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方法的签名与blueprinted方法的签名不匹配:blueprinted方法显式地省略了它的外部参数名(_),而您的方法则没有。
用最小的例子分析错误情况
我们可以构造一个类似的最小示例来获得相同的错误消息。
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!

这将产生以下错误消息:
错误:非最终类“bar”中的方法“Bar”必须返回到
符合协议“Self
 static func bar(_ baz: Int) throws -> Self { ...

如果我们将Foobar方法的签名修复为与Bar中打印的方法的签名匹配,则不再提示错误
/* ... 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
    }
}

为了避免类型推断修复(推断Foo为有效的Bar()实例),将Bar标记为Self并显式地注释final的类型
/* ... FooError and Foo as above */

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

应用于您的用例
考虑到上述情况,您需要将Self签名修改为
public static func deserialize(_ element: SWXMLHash.XMLElement) throws -> Self { /* ... */ }

或者,如果您不打算对deserialize类本身进行子类化,则将其标记为Element以允许注释具体的返回类型final,而不是Element
final class Element: XMLElementDeserializable {
    public static func deserialize(_ element: SWXMLHash.XMLElement) throws -> Element { /* ... */ }
}

(请注意,您当前的Self实现没有多大意义,因为它没有使用要反序列化的对象(内部参数名deserialized),但是既然您提到您的示例已被剥离,我将假定这是为示例准备的)。

关于swift - 在Swift 3中使用SWXMLHash反序列化类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39953031/

10-09 17:18