Class vs Structures


(Vitor Navarro) #1

Hi,

I know this question is probably done a thousand times, but I wanted to
hear from Swift dev community.

I think both of them have right places for usage depending on the occasion
but documentation, WWDC and the internet give opposite answers regarding
this.

Do you guys have any guideline regarding usage here?

Thank you.

Vitor Navarro


Struct and class
Struct and class
(^) #2

When in doubt, go with a struct. Probably nineteen types out of twenty I
write are structs. Swift really is optimized with the assumption that
you’re working with structs, that’s why almost everything in the standard
library is a value type. Structs always pack contiguously into arrays,
while arrays of classes can get bridged to a non-contiguous NSArray. Code
that uses classes tends to be hard to read since `let` and `var` cease to
convey useful information about mutability. Classes also open up cans of
worms with strong and weak ownership cycles and all that crap which is
almost completely avoidable if you know how to use value types well.

The only reason to use a class is if you really, really need reference
semantics ‚ÄĒ i.e., the instance does not have a clearly defined owner, and
you want any changes to the instance to be reflected in all of its owners.
This is rare though, and more often than not this is a code smell that
something is wrong with the larger design. Another case is when the
instance manages some kind of external resource, like a memory buffer, and
you have no other way of untangling the resource management from the life
cycle of the instance. This is why Swift array buffers are classes (though
the Array type itself is a struct which contains the buffer class).

Another case where a class *might* be appropriate is when your type
contains many many stored properties, that pushing and popping them off the
call stack by value would be slower than pushing a reference. That’s
usually a sign that you’re not making enough use of static or computed
properties though. The pass by value cost is also not as important as you
might think ‚ÄĒ small functions will get inlined by the compiler, while large
functions don’t care since the function call cost will be dwarfed by the
cost of executing the actual function body.

Inheritance and polymorphism are *not* a good enough reason to use classes;
that’s what extensions and protocols are for.

Don’t use a struct as a scoping container; use an enum for that. Some
people scope things to structs because they don’t remember that enums can
be used as a namespace, but the swift idiom is to use an enum for this, not
a struct.

tldr; structs and enums are the preferred native Swift object, classes are
really only there for programmers coming from other languages who are used
to thinking in terms of reference types.

···

On Thu, Jun 29, 2017 at 1:16 PM, Vitor Navarro via swift-users < swift-users@swift.org> wrote:

Hi,

I know this question is probably done a thousand times, but I wanted to
hear from Swift dev community.

I think both of them have right places for usage depending on the occasion
but documentation, WWDC and the internet give opposite answers regarding
this.

Do you guys have any guideline regarding usage here?

Thank you.

Vitor Navarro

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Alex Blewitt) #3

Hi,

I know this question is probably done a thousand times, but I wanted to hear from Swift dev community.

What is the question?

I think both of them have right places for usage depending on the occasion but documentation, WWDC and the internet give opposite answers regarding this.

Do you have references that you can share?

Do you guys have any guideline regarding usage here?

The Swift Programming Language sums up the similarities and differences between classes and structures quite well:

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html

Alex

···

On 29 Jun 2017, at 18:16, Vitor Navarro via swift-users <swift-users@swift.org> wrote:


(Brent Royal-Gordon) #4

Here's my suggestion: Use a class when the object represents a specific *thing* that can't be duplicated without consequence; use a struct (or enum) when the instance represents some abstract data with no concrete existence. Some examples using framework types:

* A piece of text is just some data; duplicating it doesn't do anything except maybe use more memory. So `String` should be a struct.

* A label is a particular thing that exists at a particular place on screen; if you duplicated it, you'd end up with two labels on the screen, or with an off-screen copy of a label that wouldn't have any effect when you mutated it. So `UILabel` should be a class.

* A URL is just some data; if you construct two URLs with the same contents, they are completely interchangeable. So `URL` should be a struct.

* A connection to a web server to retrieve the contents of a URL is a particular thing; if you duplicated it, you would either establish another connection, or the two instances would interfere with each other (e.g. canceling one would cancel the other). So `URLSessionTask` and `NSURLConnection` are classes.

Sometimes the same problem, approached in slightly different ways, would allow you to use either one. For instance, a database record is a particular *thing* and should probably be a class, but copy the values of the fields (perhaps omitting the ID) out of it and suddenly you have a plausible struct. As a *general* rule, it's usually better to use structs where possible because it's easier to reason about their behavior‚ÄĒmutations in one function don't suddenly pop up in a totally unrelated function‚ÄĒbut sometimes a particular type works very easily as a class and very awkwardly as a struct. Ultimately, it's a judgement call.

The other point I will make is this: "Protocol-oriented programming" is new and exciting and often very useful, but it's a tool, not a religion. If subclassing works well for your use case, then subclass away.

···

On Jun 29, 2017, at 10:40 AM, Vitor Navarro via swift-users <swift-users@swift.org> wrote:

Do you guys have any guideline regarding usage here?

--
Brent Royal-Gordon
Architechies


(Vitor Navarro) #5

Hi Taylor,

Thank you for the answer quite enlightening and also a better explanation
than the short direction given by the docs. Could you please provide a
sample for scoping with enums? I couldn't visualize it.

Thanks again.

···

2017-06-29 14:41 GMT-04:00 Taylor Swift <kelvin13ma@gmail.com>:

When in doubt, go with a struct. Probably nineteen types out of twenty I
write are structs. Swift really is optimized with the assumption that
you’re working with structs, that’s why almost everything in the standard
library is a value type. Structs always pack contiguously into arrays,
while arrays of classes can get bridged to a non-contiguous NSArray. Code
that uses classes tends to be hard to read since `let` and `var` cease to
convey useful information about mutability. Classes also open up cans of
worms with strong and weak ownership cycles and all that crap which is
almost completely avoidable if you know how to use value types well.

The only reason to use a class is if you really, really need reference
semantics ‚ÄĒ i.e., the instance does not have a clearly defined owner, and
you want any changes to the instance to be reflected in all of its owners.
This is rare though, and more often than not this is a code smell that
something is wrong with the larger design. Another case is when the
instance manages some kind of external resource, like a memory buffer, and
you have no other way of untangling the resource management from the life
cycle of the instance. This is why Swift array buffers are classes (though
the Array type itself is a struct which contains the buffer class).

Another case where a class *might* be appropriate is when your type
contains many many stored properties, that pushing and popping them off the
call stack by value would be slower than pushing a reference. That’s
usually a sign that you’re not making enough use of static or computed
properties though. The pass by value cost is also not as important as you
might think ‚ÄĒ small functions will get inlined by the compiler, while large
functions don’t care since the function call cost will be dwarfed by the
cost of executing the actual function body.

Inheritance and polymorphism are *not* a good enough reason to use
classes; that’s what extensions and protocols are for.

Don’t use a struct as a scoping container; use an enum for that. Some
people scope things to structs because they don’t remember that enums can
be used as a namespace, but the swift idiom is to use an enum for this, not
a struct.

tldr; structs and enums are the preferred native Swift object, classes are
really only there for programmers coming from other languages who are used
to thinking in terms of reference types.

On Thu, Jun 29, 2017 at 1:16 PM, Vitor Navarro via swift-users < > swift-users@swift.org> wrote:

Hi,

I know this question is probably done a thousand times, but I wanted to
hear from Swift dev community.

I think both of them have right places for usage depending on the
occasion but documentation, WWDC and the internet give opposite answers
regarding this.

Do you guys have any guideline regarding usage here?

Thank you.

Vitor Navarro

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Vitor Navarro) #6

Hi Alex,

Thank you for the reply, actually Taylor gave me a great answer which
solved my question, that was "struct or classes and when should we apply
each".

Regarding the reference I found this
https://github.com/raywenderlich/swift-style-guide#code-organization which
doesn't follow exactly the structs most of the times approach or the
protocol driven development (WWDC)

Again thanks.

···

2017-06-29 14:21 GMT-04:00 Alex Blewitt <alblue@apple.com>:

On 29 Jun 2017, at 18:16, Vitor Navarro via swift-users < > swift-users@swift.org> wrote:

Hi,

I know this question is probably done a thousand times, but I wanted to
hear from Swift dev community.

What is the question?

I think both of them have right places for usage depending on the occasion
but documentation, WWDC and the internet give opposite answers regarding
this.

Do you have references that you can share?

Do you guys have any guideline regarding usage here?

The Swift Programming Language sums up the similarities and differences
between classes and structures quite well:

https://developer.apple.com/library/content/documentation/
Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html

Alex


(Maury Markowitz) #7

The the 20th is likely when you're using one of Obj-C's features, like KVO.

···

On Jun 29, 2017, at 2:42 PM, Taylor Swift via swift-users <swift-users@swift.org> wrote:

When in doubt, go with a struct. Probably nineteen types out of twenty I write are structs.


(^) #8

An addendum: if something represents a specific ‚Äúthing‚ÄĚ that can‚Äôt be
duplicated without consequence, often that means it should be stored in one
specific place in your code, not made into a class.

···

On Fri, Jun 30, 2017 at 10:10 PM, Brent Royal-Gordon via swift-users < swift-users@swift.org> wrote:

On Jun 29, 2017, at 10:40 AM, Vitor Navarro via swift-users < > swift-users@swift.org> wrote:

Do you guys have any guideline regarding usage here?

Here's my suggestion: Use a class when the object represents a specific
*thing* that can't be duplicated without consequence; use a struct (or
enum) when the instance represents some abstract data with no concrete
existence. Some examples using framework types:

* A piece of text is just some data; duplicating it doesn't do anything
except maybe use more memory. So `String` should be a struct.

* A label is a particular thing that exists at a particular place on
screen; if you duplicated it, you'd end up with two labels on the screen,
or with an off-screen copy of a label that wouldn't have any effect when
you mutated it. So `UILabel` should be a class.

* A URL is just some data; if you construct two URLs with the same
contents, they are completely interchangeable. So `URL` should be a struct.

* A connection to a web server to retrieve the contents of a URL is a
particular thing; if you duplicated it, you would either establish another
connection, or the two instances would interfere with each other (e.g.
canceling one would cancel the other). So `URLSessionTask` and
`NSURLConnection` are classes.

Sometimes the same problem, approached in slightly different ways, would
allow you to use either one. For instance, a database record is a
particular *thing* and should probably be a class, but copy the values of
the fields (perhaps omitting the ID) out of it and suddenly you have a
plausible struct. As a *general* rule, it's usually better to use structs
where possible because it's easier to reason about their behavior‚ÄĒmutations
in one function don't suddenly pop up in a totally unrelated function‚ÄĒbut
sometimes a particular type works very easily as a class and very awkwardly
as a struct. Ultimately, it's a judgement call.

The other point I will make is this: "Protocol-oriented programming" is
new and exciting and often very useful, but it's a tool, not a religion. If
subclassing works well for your use case, then subclass away.

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(^) #9

The Ray Wenderlich style guide contains *some* useful insights, but you
should not take it as a ‚Äúswift best practices‚ÄĚ guide, or even a good code
style guide for your own projects. At the risk of sounding blunt, the RW
style guide is optimized for blog posts and cheap tutorials, not a cohesive
Swift code base you have to maintain over time. In addition that website is
heavily iOS-developer oriented, and the iOS platform forces you to interact
with a lot of Objective C frameworks which are more reference-oriented than
native Swift code should be.

Enum scoping is when you want to group free floating functions into a
common namespace to avoid polluting the global scope. For example one of
the libraries I maintain has a collection of internal math functions which
are handy to have around.

enum Math
{
    typealias IntV2 = (a:Int, b:Int)
    typealias IntV3 = (a:Int, b:Int, c:Int)
    typealias DoubleV2 = (x:Double, y:Double)
    typealias DoubleV3 = (x:Double, y:Double, z:Double)

    @inline(__always)
    private static
    func fraction(_ x:Double) -> (Int, Double)
    {
        let integer:Int = x > 0 ? Int(x) : Int(x) - 1
        return (integer, x - Double(integer))
    }

    @inline(__always)
    static
    func fraction(_ v:DoubleV2) -> (IntV2, DoubleV2)
    {
        let (i1, f1):(Int, Double) = Math.fraction(v.0),
            (i2, f2):(Int, Double) = Math.fraction(v.1)
        return ((i1, i2), (f1, f2))
    }

    @inline(__always)
    static
    func fraction(_ v:DoubleV3) -> (IntV3, DoubleV3)
    {
        let (i1, f1):(Int, Double) = Math.fraction(v.0),
            (i2, f2):(Int, Double) = Math.fraction(v.1),
            (i3, f3):(Int, Double) = Math.fraction(v.2)
        return ((i1, i2, i3), (f1, f2, f3))
    }

    @inline(__always)
    static
    func add(_ v1:IntV2, _ v2:IntV2) -> IntV2
    {
        return (v1.a + v2.a, v1.b + v2.b)
    }

    ...
}

Some, but not all projects will end up with a `Constants`, enum to store
global constants too. Beyond that, you shouldn’t be Enum scoping a lot, it
usually isn’t hard to find a real type where some method or constant
belongs. That being said, you can find a few examples of this pattern in
the Swift standard library: `Unicode`, `CommandLine` and `MemoryLayout`
come to mind.

···

On Fri, Jun 30, 2017 at 12:12 AM, Vitor Navarro via swift-users < swift-users@swift.org> wrote:

Hi Alex,

Thank you for the reply, actually Taylor gave me a great answer which
solved my question, that was "struct or classes and when should we apply
each".

Regarding the reference I found this https://github.com/
raywenderlich/swift-style-guide#code-organization which doesn't follow
exactly the structs most of the times approach or the protocol driven
development (WWDC)

Again thanks.

2017-06-29 14:21 GMT-04:00 Alex Blewitt <alblue@apple.com>:

On 29 Jun 2017, at 18:16, Vitor Navarro via swift-users < >> swift-users@swift.org> wrote:

Hi,

I know this question is probably done a thousand times, but I wanted to
hear from Swift dev community.

What is the question?

I think both of them have right places for usage depending on the
occasion but documentation, WWDC and the internet give opposite answers
regarding this.

Do you have references that you can share?

Do you guys have any guideline regarding usage here?

The Swift Programming Language sums up the similarities and differences
between classes and structures quite well:

https://developer.apple.com/library/content/documentation/Sw
ift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html

Alex

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users