2016-03-07 121 views
3

我需要用静态方法创建一个“工具”类或结构。作为来自PHP背景的人,结构并不存在。静态工具操作的静态类与静态结构?

我正在阅读关于这个Why Choose Struct Over Class?,但他们不谈论静态结构或静态类。

哪个应该用于永远不会实例化的静态方法?为什么?

例子:

struct BasicTools { 
    static func split(str: String) -> [String]{ 
     return str.characters.split{$0 == ","}.map(String.init) 
    } 
} 

VS

class BasicTools { 
    static func split(str: String) -> [String]{ 
     return str.characters.split{$0 == ","}.map(String.init) 
    } 
} 

在使用中:

let StrArr: [String] = BasicTools.split("example,example2,example3") 
+2

如果你只使用静态'functions'没有什么区别的。但是我发现第三方框架的一些函数不喜欢从'structs'内的'static functions'调用。例如,“解析”背景操作可能会以静默方式失败。从来没有真正花时间弄清楚为什么。 –

回答

2

如果你只使用静态的功能没有任何区别的。

更多结构可以用structtypealias完成。 (也是如此class但没有双关语那里)

struct MathUtils { 

    static func someMaths(withInt int:Int) -> Int { 
     return int 
    } 
} 

struct StringUtils { 

    static func someEditing(withString string:String) -> String { 
     return string 
    } 
} 

struct Utils { 

    typealias Maths = MathUtils 
    typealias Strings = StringUtils 

} 

Utils.Maths.someMaths(withInt: 10) 
1

作为R门客已指出;因为你没有这些实用程序类/结构的实例,所以它没有太大区别。

一个可能投票支持使用类在结构将是,你在其中明确限制在class使用(protocol ...: class)的协议声明你static功能非常特殊的情况:对于结构对方(protocol ...: struct)不可用。

/* only class types can conform to this protocol */ 
protocol MyClassProtocol: class { 
    static func split(str: String) -> [String] 
} 
extension MyClassProtocol { 
    static func split(str: String) -> [String]{ 
     return str.characters.split{$0 == "."}.map(String.init) 
    } 
} 

/* Use custom implementation */ 
class BasicTools: MyClassProtocol { 
    class func split(str: String) -> [String]{ 
     return str.characters.split{$0 == ","}.map(String.init) 
    } 
} 

/* Use default implementation */ 
class OtherBasicTools: MyClassProtocol { } 

BasicTools.split("foo,bar")   // ["foo", "bar"] 
OtherBasicTools.split("foo.bar") // ["foo", "bar"] 

在您的环境(的实用工具类/结构),上述:class约束为MyClassProtocol是不是真的有关。但是,如果MyClassProtocol协议---除了包含静态工具---将被用作上下文中的委托,则相关的是对该委托的强有力的引用将创建保留周期。在这种情况下,我们需要将委托协议限制为只对引用类型可用(以符合),这允许我们对委托本身使用弱引用。在这种情况下,自然我们的工具箱必须在class上下文中使用(而不是在结构中)。

例如,考虑下面的例子,我们有某些功能的静态工具箱我们希望提供给我们的所有不同类型的代表:

/* Delegate toolbox: static/class functions for use 
    with your delegates */ 
protocol MyBasicDelegateTools { 
    static func delegateCalled() ->() 
} 
extension MyBasicDelegateTools { 
    static func delegateCalled() ->() { 
     print("Logging: delegate was called") 
    } 
} 

一些代表在这里使用:

/* Delegate with access to your basic delegate tools */ 
protocol MyDelegate: class, MyBasicDelegateTools { 
    func arrUpdated(baz: [Int]) 
} 

/* It's inherrent here that we let the reference to 
    the delegate be weak, to avoid a retain cycle. */ 
class Foo { 
    private var baz : [Int] = [] { 
     didSet { 
      if let _ = delegate?.arrUpdated(baz) { 
       delegate?.dynamicType.delegateCalled() 
      } 
     } 
    } 
    weak var delegate: MyDelegate? 
} 

/* Why? Since 'foo' in 'Bar' keeps a strong reference to the 'Foo' instance */ 
class Bar: MyDelegate { 
    var foo : Foo 
    var idx: Int = 0 { 
     didSet { 
      print("idx updated: \(idx)") 
     } 
    } 

    init(foo: Foo) { 
     self.foo = foo 
     self.foo.delegate = self 
    } 

    // MyDelegate 
    func arrUpdated(baz: [Int]) { 
     idx = baz.count 
    } 
} 

用法示例:

var a = Foo() 
var b = Bar(foo: a) 

a.baz.append(1) 
    // idx updated: 1     <-- from custom delegate 
    // Logging: delegate was called <-- from delegate toolbox