斯威夫特是否有一种混合特征的方式,斯卡拉?关于使用扩展来向现有类添加协议的Swift小册子的部分非常接近。但是,由于协议不能包含实现,因此无法将代码混合到类中。还有另一种方式吗?
答案 0 :(得分:8)
从Swift 2.0开始,是的!
Providing Default Implementations
您可以使用协议扩展来提供默认实现 该协议的任何方法或财产要求。如果一个 符合类型提供了自己实现的所需方法 或属性,将使用该实现而不是该实现 由扩展提供。
答案 1 :(得分:7)
模拟混合的一种方法是使用通用函数来提供实现
例如使用这些协议
protocol Named {
func GetName() -> String
}
protocol NamedExtension {
func GetLowercaseName() -> String
func GetUppercaseName() -> String
}
我想要一些课程来实施GetName()
并使用混音,这样他们也可以获得GetLowercaseName()
和GetUppercaseName()
而不实施它们
这是免费功能
中NamedExtension
的实现
func GetLowercaseNameImpl<T:Named>(obj:T) -> String {
return obj.GetName().lowercaseString
}
func GetUppercaseNameImpl<T:Named>(obj:T) -> String {
return obj.GetName().uppercaseString
}
和Int
extension Int : Named {
func GetName() -> String {
return "Int"
}
}
extension Int : NamedExtension {
// use provided implementation
func GetLowercaseName() -> String {
return GetLowercaseNameImpl(self)
}
func GetUppercaseName() -> String {
return GetUppercaseNameImpl(self)
}
}
我可以使用
1.GetName() // result Int
1.GetUppercaseName() // result "INT"
1.GetLowercaseName() // result "int"
答案 2 :(得分:6)
我不了解Scala,但是根据您告诉我的内容,可以同时创建protocol
和extension
扩展类型以添加&#34伪 - 性状&#34;行为。
例如:
protocol IsGreaterThan
{
func isGreaterThan(other:Int) -> Bool
func isNotGreaterThan(other:Int) -> Bool
}
extension Int : IsGreaterThan
{
func isGreaterThan(other:Int) -> Bool
{
return self > other
}
func isNotGreaterThan(other:Int) -> Bool
{
return !isGreaterThan(other)
}
}
真正的腿筋是现在如何限制泛型。我认为在即将到来的Swift版本中它们会有很大的改进。
答案 3 :(得分:2)
与Bryan Chen的回答类似:
import Foundation
protocol Named {
var name : String { get }
}
protocol NamedExtension : Named { // NB extends Named
var lowercaseName : String { get }
var uppercaseName : String { get }
}
struct NamedExtensionDefault { // Put defaults inside a struct to keep name spaces seperate
static func lowercaseName(named : NamedExtension) -> String {
return (named.name as NSString).lowercaseString
}
static func uppercaseName(named : NamedExtension) -> String {
return (named.name as NSString).uppercaseString
}
}
extension Int : NamedExtension {
var name : String {
return "Int"
}
// Use default implementation
var lowercaseName : String {
return NamedExtensionDefault.lowercaseName(self)
}
var uppercaseName : String {
return NamedExtensionDefault.uppercaseName(self)
}
}
1.name // result Int
1.uppercaseName // result "INT"
1.lowercaseName // result "int"
与Bryan的答案的主要区别在于我没有使用泛型,因为我使NamedExtension
扩展Named
,因此默认实现可以访问name
。
答案 4 :(得分:1)
这是我(尚未经过广泛测试)的方式,我认为Swala 2.1.1中的Scala特性,Playgrounds-ready,两个版本:
不太灵活:
protocol BigBadProtocol {
func madFunc() -> String;
// func otherFunc();
// Maybe a couple more functions here.
}
protocol BlueMadFuncUser: BigBadProtocol {}
extension BlueMadFuncUser {
func madFunc() -> String {
return "Blue"
}
}
protocol RedMadFuncUser: BigBadProtocol {}
extension RedMadFuncUser {
func madFunc() -> String {
return "Red"
}
}
class ClearClass: BigBadProtocol {
func madFunc() -> String {
return "Clear"
}
}
class BlueClass: BlueMadFuncUser {}
class RedClass: RedMadFuncUser {}
更灵活:
protocol BigBadProtocol {
func madFunc() -> String;
// func otherFunc();
// Maybe a couple more functions here.
}
protocol BlueMadFuncUser {}
extension BigBadProtocol where Self: BlueMadFuncUser {
func madFunc() -> String {
return "Blue"
}
}
protocol RedMadFuncUser {}
extension BigBadProtocol where Self: RedMadFuncUser {
func madFunc() -> String {
return "Red"
}
}
class ClearClass: BigBadProtocol {
func madFunc() -> String {
return "Clear"
}
}
class BlueClass: BigBadProtocol, BlueMadFuncUser {}
class RedClass: BigBadProtocol, RedMadFuncUser {}
完整性检查:
var classes: [BigBadProtocol] = [ClearClass(), BlueClass(), RedClass()]
// Prints "Clear, Blue, Red\n"
print((classes.map { $0.madFunc() }).joinWithSeparator(", "))
// Print another way for Playgrounds, which appears to bug out on the lines above
var s = ""
for klass in classes {
s += klass.madFunc() + " "
}
print(s)
BlueMadFuncUser和RedMadFuncUser是两个特征的版本。我的术语可能已关闭,但您可以随意创建这样的第二个特征,并在您的课程中混合搭配。
使用基于继承的方法重用这样的逻辑会更具挑战性或更好的做法。
在Hack for PHP中发现它非常有用之后我最终想要这个模式,从我可以告诉的特性与Scala非常相似:https://docs.hhvm.com/hack/other-features/trait-and-interface-requirements)