0

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

非最终类“元素”中的方法“反序列化”必须返回Self以符合协议“XMLElementDeserializable”

我试图尽可能逐字地使用这个例子(虽然改变了很多,因为日期,一个结构,现在主要用于 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
    }

}
4

1 回答 1

3

deserialize实施没有实施蓝图

您自己的deserialize函数没有实现蓝图 from ,这意味着(from )XMLElementDeserializable的默认实现将可用于您的类。此默认实现是一个抛出错误的实现,这是您有些混淆的错误消息的来源。deserializeXMLElementDeserializableElement

来自SWXMLHash框架的源代码

/// 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!

这会产生以下错误消息:

错误:bar非最终类“”中的方法“ Bar”必须返回Self以符合协议“ Foo

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

如果我们修复barin 方法的签名Bar以匹配 in 中蓝图的签名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

/* ... 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 { /* ... */ }

或者,如果您不打算对Element类本身进行子类化,则将其标记为final允许注释具体的返回类型Element,而不是Self

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

(请注意,您当前的实现deserialized没有多大意义,因为它没有使用要反序列化的对象(内部参数 name element),但是由于您提到您的示例已被精简,因此我认为这是针对例子)。

于 2016-10-10T09:32:28.203 回答