玩Swift,来自Java背景,为什么要选择Struct而不是Class?看起来它们是一样的东西,只不过Struct提供的功能更少。那为什么选择它呢?
当前回答
从值类型和引用类型的角度来回答这个问题,从苹果博客的这篇文章来看,它看起来非常简单:
使用值类型[例如struct, enum]: 用==比较实例数据是有意义的 你希望副本有独立的状态 这些数据将在代码中跨多个线程使用 在以下情况下使用引用类型[例如class]: 比较实例标识和===是有意义的 您希望创建共享的、可变的状态
正如在那篇文章中提到的,没有可写属性的类将与结构体的行为相同,但有一点需要注意:结构体最适合线程安全模型——这是现代应用程序架构中日益迫切的需求。
其他回答
一些好处:
由于不可共享,自动线程安全 由于没有isa和refcount,使用更少的内存(实际上通常是堆栈分配) 方法总是静态分派的,所以可以内联(尽管@final可以为类这样做) 更容易推理(不需要“防御性复制”,这是典型的NSArray, NSString等…)出于与线程安全相同的原因
对于类,您获得继承并通过引用传递,而结构则没有继承并通过值传递。
有很多关于Swift的WWDC会议,其中一个会议详细回答了这个问题。确保你看了这些,因为它会让你更快地跟上语言指南或iBook。
Structure and class are user defied data types By default, structure is a public whereas class is private Class implements the principal of encapsulation Objects of a class are created on the heap memory Class is used for re usability whereas structure is used for grouping the data in the same structure Structure data members cannot be initialized directly but they can be assigned by the outside the structure Class data members can be initialized directly by the parameter less constructor and assigned by the parameterized constructor
许多Cocoa api需要NSObject子类,这迫使你使用class。但除此之外,你可以使用以下苹果Swift博客中的案例来决定是使用struct / enum值类型还是类引用类型。
https://developer.apple.com/swift/blog/?id=10
我不会说结构体提供的功能更少。
当然,self是不可变的,除了在突变函数中,但仅此而已。
继承可以很好地工作,只要您坚持每个类都应该是抽象的或最终的。
将抽象类实现为协议,将最终类实现为结构。
struct的好处是你可以在不创建共享可变状态的情况下使你的字段可变,因为写时复制会照顾到这一点:)
这就是为什么下面例子中的属性/字段都是可变的,我不会在Java或c#或swift类中这样做。
示例继承结构,在底部名为" Example "的函数中有一点脏和直接的用法:
protocol EventVisitor
{
func visit(event: TimeEvent)
func visit(event: StatusEvent)
}
protocol Event
{
var ts: Int64 { get set }
func accept(visitor: EventVisitor)
}
struct TimeEvent : Event
{
var ts: Int64
var time: Int64
func accept(visitor: EventVisitor)
{
visitor.visit(self)
}
}
protocol StatusEventVisitor
{
func visit(event: StatusLostStatusEvent)
func visit(event: StatusChangedStatusEvent)
}
protocol StatusEvent : Event
{
var deviceId: Int64 { get set }
func accept(visitor: StatusEventVisitor)
}
struct StatusLostStatusEvent : StatusEvent
{
var ts: Int64
var deviceId: Int64
var reason: String
func accept(visitor: EventVisitor)
{
visitor.visit(self)
}
func accept(visitor: StatusEventVisitor)
{
visitor.visit(self)
}
}
struct StatusChangedStatusEvent : StatusEvent
{
var ts: Int64
var deviceId: Int64
var newStatus: UInt32
var oldStatus: UInt32
func accept(visitor: EventVisitor)
{
visitor.visit(self)
}
func accept(visitor: StatusEventVisitor)
{
visitor.visit(self)
}
}
func readEvent(fd: Int) -> Event
{
return TimeEvent(ts: 123, time: 56789)
}
func example()
{
class Visitor : EventVisitor
{
var status: UInt32 = 3;
func visit(event: TimeEvent)
{
print("A time event: \(event)")
}
func visit(event: StatusEvent)
{
print("A status event: \(event)")
if let change = event as? StatusChangedStatusEvent
{
status = change.newStatus
}
}
}
let visitor = Visitor()
readEvent(1).accept(visitor)
print("status: \(visitor.status)")
}