微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Swift 2.0协议扩展和Java / C#抽象类之间有区别吗?

通过在 Swift 2.0中添加协议扩展,似乎协议基本上成为Java / C#抽象类.我唯一可以看到的不同之处在于抽象类限制为单一继承,而Swift类型可以符合任何数量的协议.

这是对Swift 2.0中的协议的正确理解,还是有其他差异?

有几个重要的区别…

协议扩展可以与value types以及类共同使用.

值类型是结构体和枚举.例如,您可以扩展IntegerArithmeticType以将isPrime属性添加到所有整数类型(UInt8,Int32等).或者,您可以将协议扩展与结构扩展组合,以将相同的功能添加到多个现有类型 – 例如,向CGPoint和CGVector添加向量算术支持.

Java和C#在一个语言层面上并没有真正具有用户创建/可扩展的“普通旧数据”类型,所以在这里没有一个模拟. Swift使用值类型很多 – 与ObjC,C#和Java不同,Swift甚至集合都是拷贝的值类型.这有助于解决很多关于可变性和线程安全性的问题,所以创建自己的值类型而不是总是使用类可以帮助您编写更好的代码. (见WWDC15 Building Better Apps with Value Types in Swift)

协议扩展可以被约束.

例如,只有当集合的底层元素类型符合某些条件时,才能有一个CollectionType添加方法的扩展.这是找到一个集合的最大元素 – 在一个数字或字符串的集合上,此属性显示,但在一组(例如UIViews(不是Comparable))上,此属性不存在.

extension CollectionType where Self.Generator.Element: Comparable {
    var max: Self.Generator.Element {
        var best = self[self.startIndex]
        for elt in self {
            if elt > best {
                best = elt
            }
        }
        return best
    }
}

(帽子提示:这个例子在今天出色的NSBlog上出现.)

在这些WWDC15会议中,还有一些比较有限的协议扩展的例子(可能还有更多的,但我还没有抓住视频):

> Protocol-Oriented Programming in Swift
> Swift in Practice

抽象类 – 无论使用什么语言,包括ObjC或Swift,它们是编码约定而不是语言特性 – 沿类继承行工作,因此所有子类都继承抽象类的功能,无论是否有意义.

协议可以选择静态或动态调度.

这更像是一个头痛的人,但如果使用得当,可以真的很强大.这是一个基本的例子(从NSBlog开始):

protocol P {
    func a()
}
extension P {
    func a() { print("default implementation of A") }
    func b() { print("default implementation of B") }
}
struct S: P {
    func a() { print("specialized implementation of A") }
    func b() { print("specialized implementation of B") }
}

let p: P = S()
p.a() // -> "specialized implementation of A"
p.b() // -> "default implementation of B"

正如苹果在Protocol-Oriented Programming in Swift注释的那样,您可以使用它来选择哪些功能应该被覆盖点,这些点可以由采用协议的客户端定制,哪些功能应该始终是协议提供的标准功能.

一种类型可以从多个协议获得扩展功能.

正如你已经指出的那样,协议一致性是一种多重继承的形式.如果您的类型符合多种协议,并且这些协议具有扩展名,那么您的类型将获得所有扩展的功能,该扩展的约束符合.

您可能会意识到为类提供多重继承的其他语言,其中会打开一个丑陋的蠕虫,因为您不知道如果您从具有相同成员或功能的多个类继承可能会发生什么. Swift 2在这方面有点好一点:

>协议扩展之间的冲突是always resolved in favor of the most constrained extension.因此,例如,一个视图集合的方法总是胜过任意集合上相同命名的方法(这又反过来胜过任意序列上的同名方法,因为CollectionType是一个子类型的SequenceType).
调用一个否则冲突的API是编译错误,而不是运行时模糊.

协议(和扩展)无法创建存储.

协议定义可以要求采用协议的类型必须实现一个属性

protocol Named {
    var name: String { get } // or { get set } for readwrite 
}

采用协议的类型可以选择是否将其实现为存储属性或计算属性,但是无论哪种方式,采用类型都必须声明其实现属性.

扩展可以实现一个计算属性,但扩展名不能添加存储的属性.无论是协议扩展还是特定类型(类,结构体或枚举)的扩展名,都是如此.

相比之下,类可以添加要由子类使用的存储属性.虽然Swift中没有语言功能来强制超类是抽象的(也就是说,您无法使编译器禁止实例创建),但如果要使用此功能,则可以非正式地创建“抽象”超类.

原文地址:https://www.jb51.cc/swift/319778.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐