使用 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 { ...
如果我们修复 Bar
中 bar
方法的签名以匹配 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
) ,但是既然你提到你的例子被精简了,我会假设这是为了这个例子)。
我正在尝试使用自述文件末尾提供的示例将 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 returnSelf
to conform to protocol 'Foo
'static func bar(_ baz: Int) throws -> Self { ...
如果我们修复 Bar
中 bar
方法的签名以匹配 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
) ,但是既然你提到你的例子被精简了,我会假设这是为了这个例子)。