此代码生成Xcode错误消息,引导您进入一个圆圈。假设我有一个名为static string GetBuildMonthDay()
{
var version = typeof(Test).GetTypeInfo().Assembly.GetName().Version;
var buildDateTime = new DateTime(2000, 1, 1)
.AddDays(version.Build)
.AddSeconds(version.Revision * 2);
return buildDateTime.ToString("Mdd", CultureInfo.InvariantCulture);
}
的协议,我想让Markers复制自己。这是第一次猜测......
Marker
(我不确定如何正确使用protocol Marker {
func copy() -> Self
}
class Marker1 : Marker {
func copy() -> Self {
return Marker1() // error here
}
}
,因为我无法在 Swift编程语言文档中找到它。如果你知道它在哪里记录,请包括回答。)
该代码在标记的行上显示错误:Self
并且它建议修复:Cannot convert return expression of type 'Marker1' to return type 'Self'
。
我接受修复:
Insert ' as! Self'
这会导致另一个编译器错误:...
return Marker1() as! Self
...
如果我接受“修复”,则会返回原始错误。我称之为Xcode中的一个错误。我们试试别的:
'Self' is only available in a protocol or as the result of a method in a class; did you mean 'Marker1'?
另一个错误:func copy() -> Marker1 {
return Marker1()
}
使类Method 'copy()' in non-final class 'Marker1' must return `Self` to conform to protocol 'Marker'
确实可以修复错误。但有没有办法在没有上课的情况下做到这一点? final
在哪里记录?
答案 0 :(得分:3)
使用这样的层次结构,您必须使该类符合协议final
:
protocol Marker {
func copy() -> Self
}
final class Marker1 : Marker {
func copy() -> Marker1 {
return Marker1()
}
}
需要final
,因为当您不申请final
并创建子类Marker2: Marker1
时,复制将不再返回正确的类Self
您可以通过创建required
初始化程序并始终创建正确的实例来解决此问题:
protocol Marker {
init()
func copy() -> Self
}
class Marker1 : Marker {
required init() {
}
func copy() -> Self {
let copy = type(of: self).init()
return copy
}
}
(删除原始代码,因为不起作用)
答案 1 :(得分:1)
当前实现的问题是Self
是一种抽象类型,因此您不能简单地从返回类型为Marker1
的函数中返回具体类型,例如Self
。如果将返回类型更改为Marker1
,则需要使类最终确保没有子类可以覆盖该方法,因为在子类中,Self
将对应于子类类型。但是,这仍然不好,因为在这种情况下子类将不符合协议,因为在Marker1
的子类中,Marker1
的返回类型与{{1}不同}。
您可以通过使用self
获取当前类的元类型来解决此问题,然后在元类型上调用指定的初始化程序,这将确实返回类型为type(of: self)
的实例。最后一步是为您的类创建一个必需的初始化程序,以确保所有子类都需要实现在Self
方法中调用的相同初始化程序,以使copy()
也适用于子类。
copy