Unify `static` and `class` keywords

Please remember that stored properties can be overridden in Swift:

class Base {
  /*instance*/ var flag: Bool = true
}

class Sub : Base {
  override var flag: Bool {
    didSet {
      if flag { print("The flag was set!") }
    }
  }
}

This is theoretically possible at the class level as well, but doesn't really make sense for what's currently spelled "static var", since you'd be accessing the same storage in different ways. Does the proposal mean that a stored "type var" is non-overrideable, but a computed "type var" is overrideable, implicitly?

Jordan

···

On Dec 7, 2015, at 19:12, Ling Wang via swift-evolution <swift-evolution@swift.org> wrote:

Besides, we shouldn’t use `final` to denote storage at all for `final` is about inheritability/overridability not about storage.

The problem is one of consistency. It would be very problematic for a “type var” to have one set of semantics, but a “type func” to have completely different semantics. Also keep in mind that we *do* have *computed* static and computed class properties, today.

-Chris

···

On Dec 7, 2015, at 7:12 PM, Ling Wang via swift-evolution <swift-evolution@swift.org> wrote:

Now I understand your concerns. But you misunderstood my proposal. I'll restate my points about “type properties”:

1. Stored class properties(let’s call them “class instance variables” for better discussion about “stored type properties” below) are not very useful or needed. So we are not likely to add them to Swift. This one we both agree. So there is only one kind of stored properties for types and they are stored like global variables, which are now called “static stored properties“.

2. `type` properties in my proposal covers both stored properties and calculated properties. Except for the `type` keyword, the way they are declared are exactly the same as that of instance properties:

class Foo {
    type let i = 1 // stored type property
    type var k: Int { // calculated type property
        return 1
    }
} 

3. Since we’ve already excluded “class instance variables” in point 1, stored type properies in my proposal are certainly not “class instance variables”. They behave the same as the current “static stored properties”. This is where you misunderstood me.

So you don’t need the `final` keyword to make them “static”. If they are “stored”(VS calculated) they are “static”. We just don’t use `static` as the keyword.

Static storage is the implementation details. Just like global variable declarations don’t need `static` keyword though they use static storage, stored type property declarations don’t need `static` keyword to denote they use static storage. After all there is only one kind of stored type properties.

+1 No matter what keyword we end up with, I'm very strongly in favor of this proposal too.

R+

···

Sent from my iPhone

On 07 Dec 2015, at 21:08, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

I must have missed the initial link to the proposal. This is very well thought out and I support it very strongly. My opinion on the keyword is not strong enough to matter and I would support whatever keyword has the most consensus.

I think my own confusion about static vs final class demonstrates the problem with the current state.

Sent from my iPad

On Dec 7, 2015, at 1:38 PM, an0 <an00na@gmail.com> wrote:

I've already addressed that under "Class stored properties VS. static
stored properties"(https://github.com/an0/swift-evolution/blob/master/proposals/NNNN-unify-static-and-class-keywords.md#class-stored-properties-vs-static-stored-properties\).
I don't think we'll add class stored properties to Swift though. It is
one of the premises of this proposal.

On Mon, Dec 7, 2015 at 1:22 PM, John McCall <rjmccall@apple.com> wrote:

On Dec 7, 2015, at 10:56 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

I think unifying these keywords would make a lot of sense, but neither would really be suitable as the unified choice. 'class' would be out of place in structs and enums. 'static' would be out of place for members that can be overridden in a class.

If we do unify this keyword, I believe combining it with 'final' in a class would recover the behavior we currently get when using 'static' in a class. (If this is not correct I would want to know how we achieve that behavior with the unified keyword)

There are a lot of drawbacks to using 'type' and I think we should find something better.

One important difference between “static” and “class” on a class is the behavior of storage. In principle, a static variable in a class is just a rescoped global (although it is unclear how this is affected by generics). A class variable in a class is conceptually a member of the class, and subclasses should get a separate copy.

John.

Sent from my iPad

On Dec 7, 2015, at 12:11 PM, Ling Wang via swift-evolution <swift-evolution@swift.org> wrote:

`type` is the best I can come up with so far. Using `type` to declare type members inside types is completely parallel with using `class` to declare class members inside classes, so conceptually it should be easy to accept. It may look a bit uncomfortable at first simply because it is new and different, especially to those with C++ and Java experiences.

On Dec 7, 2015, at 11:01 AM, David Hart <david@hartbit.com> wrote:

I really like this proposition, but I'm not a fan of the keyword, but can't think of anything better right now...

On 07 Dec 2015, at 17:13, an0 via swift-evolution <swift-evolution@swift.org> wrote:

The idea is simple but the reasoning is long. So please bear with me.
You can read on github for a better reading experience:
https://github.com/an0/swift-evolution/blob/master/proposals/NNNN-unify-static-and-class-keywords.md\.

## Introduction

The coexistence of `static` and `class` keywords for declaring type
properties and methods is confusing and causes inconsistency between
type and instance member declarations. This document reasons why we
don’t need both and suggests we unify them with a better keyword
`type`.

## Motivation

### Confusion

One “language enhancement” of [Swift
1.2](https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc6_release_notes.html#//apple_ref/doc/uid/TP40001051-CH4-SW6\)
is:

“static” methods and properties are now allowed in classes (as an alias for class final). You are now allowed to declare static stored properties in classes, which have global storage and are lazily initialized on first access (like global variables). Protocols now declare type requirements as static requirements instead of declaring them as class requirements. (17198298)

If even the Swift team itself has difficulties in picking one from the
two and had to revert its initial decision after several revisions, we
know these keywords are indeed confusing.

So now protocols use `static` to declare type methods, when a class
adapts such protocols, should it implement those static methods, as
static methods or class methods?

But static means final, right? Does it mean we can not override these
methods in subclasses of the conforming class?

These kinds of unnecessary confusion and hesitation should be
resolved, and could if this proposal is implemented.

### Unnecessary and inconsistent differentiation

The `class` keyword is only used in classes. In the current
implementation of Swift the differences between `class` and `static`
are:

1. Class properties can only be calculated properties but not stored properties.
2. Class methods(also calculated properties) are dynamically
dispatched while static ones are statically dispatched.

If we can eliminate the differences or find better ways to
differentiate we can use one unified keyword instead for declaring
type properties and methods.

Let’s see.

#### Class stored properties VS. static stored properties

If you use the `class` keyword to declare a stored property in a class
you will get this compiling error:

class stored properties not yet supported in classes; did you mean 'static'?

So what are class stored properties? How are they different from
static stored properties?

As far as I know, class stored properties, if ever implemented in
Swift, “would be what Ruby calls ‘class instance
variables’”.<sup>[1](https://twitter.com/UINT_MIN/status/584104757117095936\)</sup>

So what are class instance variables?

The best explanation I can find is this
[one](http://martinfowler.com/bliki/ClassInstanceVariable.html\) from
Martin Fowler.

Do we really want this feature in Swift? “If we didn't already have
these, would we add them to Swift 3?"

I strongly believe we won’t add it to Swift 3. Actually I believe we
will never add it to Swift, because its use cases are so rare which is
also why it hasn’t been implemented so far in Swift.

If we agree we are not going to support class stored properties, there
is and will be only one kind of stored properties for types and we
only need one keyword to declare such properties.

#### Class methods VS. static methods

*Since calculated properties are also methods in essence they are also
covered by this section.*

The only difference is how methods are dispatched.

Let’s see [how we handle it for instance
methods](Swift Blog - Apple Developer):

* Methods are overridable hence dynamically dispatched by default.
* In performance critical code use these techniques to restrict this
dynamic behavior when it isn’t needed to improve performance:

1. Use the `final` keyword when we know that a declaration does
not need to be overridden.
2. Infer `final` on declarations referenced in one file by
applying the `private` keyword.
3. Use `Whole Module Optimization` to infer `final` on `internal`
declarations.

So why abandon this whole system to use another totally different one
for differentiating `static dispatch` and `dynamic dispatch` for type
methods?

If we reuse this system for type methods, not only can we have a
consistent design for both instance and type methods, but also we can
get rid of the last place where two keywords for type member
declarations are needed.

## Proposed solution

1. Use the keyword `type` to declare type properties and methods.
2. Type properties and methods are overridable hence dynamically
dispatched by default. Use the `final` keyword or inferred `final` to
make them final and statically dispatched, just like instance
properties and methods.
3. Type properties can be stored or calculated, just like instance properties.

As you can see, it is a very simple and elegant design:

* Just a single keyword `type` to differentiate type member
declarations from instance member declarations. `type` is a good
keyword because:

1. It is consistent with the wording of the concepts of `type
properties` and `type methods`.
2. It is never used as a keyword before in Swift, Objective-C or
C. There will be no conflicts or overloading of it meanings.
* Except for that, how things are declared, differentiated and
optimized are exactly the same in both type and instance world. Very
consistent.

## Comparison with current design

* Dynamic Dispatch VS. Static Dispatch

// Old
class Foo {
func dynamicInstanceMethod() {}
final func staticInstanceMethod() {}

class func dynamicTypeMethod() {}
static func staticTypeMethod() {}
}
// New
class Foo {
func dynamicInstanceMethod() {}
final func staticInstanceMethod() {}

type func dynamicTypeMethod() {}
final type func staticTypeMethod() {}
}

* Stored Properties VS. Calculated Properties

// Old
class Bar {
static let i = 1

class var j: Int {
  return 1
}
}
// New
class Bar {
type let i = 1

type var j: Int {
  return 1
}
}

* Struct Implementation VS. Class Implementation of Protocol

// Old
protocol P {
static func foo()
}

struct S: P {
static func foo() {}
}

class C: P {
class func foo() {}
}
// New
protocol P {
type func foo()
}

struct S: P {
type func foo() {}
}

class C: P {
type func foo() {}
}

## Impact on existing code

With the help of a good migration tool, there will be no impact on
existing code at all. And the migration rules are very clear and
simple:

* Map `static` to `type` in protocols.
* Map `static` to `type` in structs and enums.
* Map `class` to `type` and `static` to `final type` in classes.

One concern I can think of is: because type methods are dynamically
dispatched by default in the new design, will we forget to do the
`final` optimization so the general performance of Swift code become
worse?

I think it is probably true. But we also forget to do the `final`
optimization for instance methods from time to time. Since there are
way more instance methods than type methods in most code the
performance impact will be very small. Maybe this change is a good
opportunity to remind us to do the `final` optimization for instance
methods thus even results in a better general performance.

And don’t forget we have the tools to automatically infer `final` for
us in many cases if we write the proper code and use the proper
compiler features.

After all, it is mainly on us to write good code to produce good final
products. If the system is consistent we’ll have better chances to
master it and use it properly.

## Alternatives considered

Alternatively we could:
* Keep using `static` and `class` keywords.
* Keep the confusion when implementing `static` protocol requirements
using `class` properties and methods in conforming classes.
* Keep the inconsistency between type member declarations and instance
member declarations.
* Keep overloading meanings on the `static` keyword that is already
historically overloaded in C and Objective-C with which Swift must mix
and match.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

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

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

--
wangling.me

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

Yes, the `static` is badly overloaded with many different meanings:
1. static storage (old, from C)
2. static linking (old, from C)
3. final (new in Swift)

That’s why I’m proposing we use a new keyword. My initial suggestion is `type` but I welcome any better alternative.

`overridable` is unnecessary since we already have `final`.

···

On Dec 8, 2015, at 7:33 AM, Daniel Valls Estella <daniel@upzzle.com> wrote:

Just if it helps someway, in my opinion:

- static is well known keyword modifier from long ago, but I think is an unfortunate one because is named that way from a complier point fo view, not from a language programmer user.

- I don’t understand static as having an implicit final behaviour.

- It seems we want to mix in one word parallel variables modifiers when is not a goal reduce code typing.

- I found confusing using class keyword instead of static just to note that a static computed variable is not final (same for methods). More when the language provides the final keyword to identify this behaviour.

- why not ?

class SomeClass {

    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 27
    }
    static final var nonOverrideableComputedTypeProperty: Int {
        return 107
    }
}

-But as I mentioned I think static is not a good keyword, only we have been used to it.

Maybe shared ? Adding overridable in case?

class SomeClass {
    shared var storedTypeProperty = “Some value."
    shared var computedTypeProperty: Int {
        return 27
    }
    shared overridable var overrideableComputedTypeProperty: Int {
        return 107
    }
}

Or:

class SomeClass {
    shared var storedTypeProperty = “Some value."
    shared var computedTypeProperty: Int {
        return 27
    }
    shared final var nonOverrideableComputedTypeProperty: Int {
        return 107
    }
}

Thanks,

Daniel

Fragment de: Apple Inc. “The Swift Programming Language (Swift 2.2)“. iBooks.

Fragment de: Apple Inc. “The Swift Programming Language (Swift 2.2)“. iBooks.

El 8 des 2015, a les 5:22, J. Cheyo Jimenez via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> va escriure:

Hi Ling,

In April 2015 you said on your blog that "I was not convinced so I filed an radar." It would seem to me that you are not convinced now either, even after Chris explained that what you are asking for was implemented, reverted and ultimately rejected. I appreciate the fact that you are thinking and worry about the apparent inconstancy. I rather the swift swift team spend more time focusing on ABI stability than on non issue items. Swift is young. Who knows maybe your ideas will make it in a future version of Swift.

wangling.me/2015/04/unify-type-properties-and-methods.html <http://wangling.me/2015/04/unify-type-properties-and-methods.html&gt;
Apple Developer Forums

On Monday, December 7, 2015, an0 <an00na@gmail.com <mailto:an00na@gmail.com>> wrote:
I read that. But that's a long time ago, Swift has evolved a lot since then. I believe the Swift team may have some new ideas about it or at least could take a look at the ideas in this proposal.

Do you have any ideas of your own about this proposal? I'd really like to learn:)

On Mon, Dec 7, 2015 at 12:49 PM J. Cheyo Jimenez <cheyo@masters3d.com <javascript:_e(%7B%7D,'cvml','cheyo@masters3d.com');>> wrote:
ChrisLattner wrote:

We considered unifying the syntax (e.g. using "type" as the keyword), but that doesn't actually simply things. The keywords "class" and "static" are good for familiarity and are quite descriptive (once you understand how + methods work), and open the door for potentially adding truly static methods to classes. The primary weirdness of this model is that protocols have to pick a keyword (and we chose "class"), but on balance it is the right tradeoff.

-Chris
Jul 5, 2014

Apple Developer Forums

On Monday, December 7, 2015, an0 via swift-evolution <swift-evolution@swift.org <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:
The idea is simple but the reasoning is long. So please bear with me.
You can read on github for a better reading experience:
https://github.com/an0/swift-evolution/blob/master/proposals/NNNN-unify-static-and-class-keywords.md\.

## Introduction

The coexistence of `static` and `class` keywords for declaring type
properties and methods is confusing and causes inconsistency between
type and instance member declarations. This document reasons why we
don’t need both and suggests we unify them with a better keyword
`type`.

## Motivation

### Confusion

One “language enhancement” of [Swift
1.2](https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc6_release_notes.html#//apple_ref/doc/uid/TP40001051-CH4-SW6\)
is:
> “static” methods and properties are now allowed in classes (as an alias for class final). You are now allowed to declare static stored properties in classes, which have global storage and are lazily initialized on first access (like global variables). Protocols now declare type requirements as static requirements instead of declaring them as class requirements. (17198298)

If even the Swift team itself has difficulties in picking one from the
two and had to revert its initial decision after several revisions, we
know these keywords are indeed confusing.

So now protocols use `static` to declare type methods, when a class
adapts such protocols, should it implement those static methods, as
static methods or class methods?

But static means final, right? Does it mean we can not override these
methods in subclasses of the conforming class?

These kinds of unnecessary confusion and hesitation should be
resolved, and could if this proposal is implemented.

### Unnecessary and inconsistent differentiation

The `class` keyword is only used in classes. In the current
implementation of Swift the differences between `class` and `static`
are:

1. Class properties can only be calculated properties but not stored properties.
2. Class methods(also calculated properties) are dynamically
dispatched while static ones are statically dispatched.

If we can eliminate the differences or find better ways to
differentiate we can use one unified keyword instead for declaring
type properties and methods.

Let’s see.

#### Class stored properties VS. static stored properties

If you use the `class` keyword to declare a stored property in a class
you will get this compiling error:
> class stored properties not yet supported in classes; did you mean 'static'?

So what are class stored properties? How are they different from
static stored properties?

As far as I know, class stored properties, if ever implemented in
Swift, “would be what Ruby calls ‘class instance
variables’”.<sup>[1](https://twitter.com/UINT_MIN/status/584104757117095936\)</sup>

So what are class instance variables?

The best explanation I can find is this
[one](http://martinfowler.com/bliki/ClassInstanceVariable.html\) from
Martin Fowler.

Do we really want this feature in Swift? “If we didn't already have
these, would we add them to Swift 3?"

I strongly believe we won’t add it to Swift 3. Actually I believe we
will never add it to Swift, because its use cases are so rare which is
also why it hasn’t been implemented so far in Swift.

If we agree we are not going to support class stored properties, there
is and will be only one kind of stored properties for types and we
only need one keyword to declare such properties.

#### Class methods VS. static methods

*Since calculated properties are also methods in essence they are also
covered by this section.*

The only difference is how methods are dispatched.

Let’s see [how we handle it for instance
methods](Increasing Performance by Reducing Dynamic Dispatch - Swift Blog - Apple Developer <Increasing Performance by Reducing Dynamic Dispatch - Swift Blog - Apple Developer):

* Methods are overridable hence dynamically dispatched by default.
* In performance critical code use these techniques to restrict this
dynamic behavior when it isn’t needed to improve performance:

    1. Use the `final` keyword when we know that a declaration does
not need to be overridden.
    2. Infer `final` on declarations referenced in one file by
applying the `private` keyword.
    3. Use `Whole Module Optimization` to infer `final` on `internal`
declarations.

So why abandon this whole system to use another totally different one
for differentiating `static dispatch` and `dynamic dispatch` for type
methods?

If we reuse this system for type methods, not only can we have a
consistent design for both instance and type methods, but also we can
get rid of the last place where two keywords for type member
declarations are needed.

## Proposed solution

1. Use the keyword `type` to declare type properties and methods.
2. Type properties and methods are overridable hence dynamically
dispatched by default. Use the `final` keyword or inferred `final` to
make them final and statically dispatched, just like instance
properties and methods.
3. Type properties can be stored or calculated, just like instance properties.

As you can see, it is a very simple and elegant design:

* Just a single keyword `type` to differentiate type member
declarations from instance member declarations. `type` is a good
keyword because:

    1. It is consistent with the wording of the concepts of `type
properties` and `type methods`.
    2. It is never used as a keyword before in Swift, Objective-C or
C. There will be no conflicts or overloading of it meanings.
* Except for that, how things are declared, differentiated and
optimized are exactly the same in both type and instance world. Very
consistent.

## Comparison with current design

* Dynamic Dispatch VS. Static Dispatch

// Old
class Foo {
    func dynamicInstanceMethod() {}
    final func staticInstanceMethod() {}

    class func dynamicTypeMethod() {}
    static func staticTypeMethod() {}
}
// New
class Foo {
    func dynamicInstanceMethod() {}
    final func staticInstanceMethod() {}

    type func dynamicTypeMethod() {}
    final type func staticTypeMethod() {}
}

* Stored Properties VS. Calculated Properties

// Old
class Bar {
    static let i = 1

    class var j: Int {
        return 1
    }
}
// New
class Bar {
    type let i = 1

    type var j: Int {
        return 1
    }
}

* Struct Implementation VS. Class Implementation of Protocol

// Old
protocol P {
    static func foo()
}

struct S: P {
    static func foo() {}
}

class C: P {
    class func foo() {}
}
// New
protocol P {
    type func foo()
}

struct S: P {
    type func foo() {}
}

class C: P {
    type func foo() {}
}

## Impact on existing code

With the help of a good migration tool, there will be no impact on
existing code at all. And the migration rules are very clear and
simple:

* Map `static` to `type` in protocols.
* Map `static` to `type` in structs and enums.
* Map `class` to `type` and `static` to `final type` in classes.

One concern I can think of is: because type methods are dynamically
dispatched by default in the new design, will we forget to do the
`final` optimization so the general performance of Swift code become
worse?

I think it is probably true. But we also forget to do the `final`
optimization for instance methods from time to time. Since there are
way more instance methods than type methods in most code the
performance impact will be very small. Maybe this change is a good
opportunity to remind us to do the `final` optimization for instance
methods thus even results in a better general performance.

And don’t forget we have the tools to automatically infer `final` for
us in many cases if we write the proper code and use the proper
compiler features.

After all, it is mainly on us to write good code to produce good final
products. If the system is consistent we’ll have better chances to
master it and use it properly.

## Alternatives considered

Alternatively we could:
* Keep using `static` and `class` keywords.
* Keep the confusion when implementing `static` protocol requirements
using `class` properties and methods in conforming classes.
* Keep the inconsistency between type member declarations and instance
member declarations.
* Keep overloading meanings on the `static` keyword that is already
historically overloaded in C and Objective-C with which Swift must mix
and match.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

`overridable` is unnecessary since we already have `final`.

Agree in part, but it’s to keep the current behaviour of being final by default, without anotating it, that maybe is a better aproach for shared properties.

···

El 8 des 2015, a les 16:51, Ling Wang <an00na@gmail.com> va escriure:

Yes, the `static` is badly overloaded with many different meanings:
1. static storage (old, from C)
2. static linking (old, from C)
3. final (new in Swift)

That’s why I’m proposing we use a new keyword. My initial suggestion is `type` but I welcome any better alternative.

On Dec 8, 2015, at 7:33 AM, Daniel Valls Estella <daniel@upzzle.com <mailto:daniel@upzzle.com>> wrote:

Just if it helps someway, in my opinion:

- static is well known keyword modifier from long ago, but I think is an unfortunate one because is named that way from a complier point fo view, not from a language programmer user.

- I don’t understand static as having an implicit final behaviour.

- It seems we want to mix in one word parallel variables modifiers when is not a goal reduce code typing.

- I found confusing using class keyword instead of static just to note that a static computed variable is not final (same for methods). More when the language provides the final keyword to identify this behaviour.

- why not ?

class SomeClass {

    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 27
    }
    static final var nonOverrideableComputedTypeProperty: Int {
        return 107
    }
}

-But as I mentioned I think static is not a good keyword, only we have been used to it.

Maybe shared ? Adding overridable in case?

class SomeClass {
    shared var storedTypeProperty = “Some value."
    shared var computedTypeProperty: Int {
        return 27
    }
    shared overridable var overrideableComputedTypeProperty: Int {
        return 107
    }
}

Or:

class SomeClass {
    shared var storedTypeProperty = “Some value."
    shared var computedTypeProperty: Int {
        return 27
    }
    shared final var nonOverrideableComputedTypeProperty: Int {
        return 107
    }
}

Thanks,

Daniel

Fragment de: Apple Inc. “The Swift Programming Language (Swift 2.2)“. iBooks.

Fragment de: Apple Inc. “The Swift Programming Language (Swift 2.2)“. iBooks.

El 8 des 2015, a les 5:22, J. Cheyo Jimenez via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> va escriure:

Hi Ling,

In April 2015 you said on your blog that "I was not convinced so I filed an radar." It would seem to me that you are not convinced now either, even after Chris explained that what you are asking for was implemented, reverted and ultimately rejected. I appreciate the fact that you are thinking and worry about the apparent inconstancy. I rather the swift swift team spend more time focusing on ABI stability than on non issue items. Swift is young. Who knows maybe your ideas will make it in a future version of Swift.

wangling.me/2015/04/unify-type-properties-and-methods.html <http://wangling.me/2015/04/unify-type-properties-and-methods.html&gt;
Apple Developer Forums

On Monday, December 7, 2015, an0 <an00na@gmail.com <mailto:an00na@gmail.com>> wrote:
I read that. But that's a long time ago, Swift has evolved a lot since then. I believe the Swift team may have some new ideas about it or at least could take a look at the ideas in this proposal.

Do you have any ideas of your own about this proposal? I'd really like to learn:)

On Mon, Dec 7, 2015 at 12:49 PM J. Cheyo Jimenez <cheyo@masters3d.com <javascript:_e(%7B%7D,'cvml','cheyo@masters3d.com');>> wrote:
ChrisLattner wrote:

We considered unifying the syntax (e.g. using "type" as the keyword), but that doesn't actually simply things. The keywords "class" and "static" are good for familiarity and are quite descriptive (once you understand how + methods work), and open the door for potentially adding truly static methods to classes. The primary weirdness of this model is that protocols have to pick a keyword (and we chose "class"), but on balance it is the right tradeoff.

-Chris
Jul 5, 2014

Apple Developer Forums

On Monday, December 7, 2015, an0 via swift-evolution <swift-evolution@swift.org <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:
The idea is simple but the reasoning is long. So please bear with me.
You can read on github for a better reading experience:
https://github.com/an0/swift-evolution/blob/master/proposals/NNNN-unify-static-and-class-keywords.md\.

## Introduction

The coexistence of `static` and `class` keywords for declaring type
properties and methods is confusing and causes inconsistency between
type and instance member declarations. This document reasons why we
don’t need both and suggests we unify them with a better keyword
`type`.

## Motivation

### Confusion

One “language enhancement” of [Swift
1.2](https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc6_release_notes.html#//apple_ref/doc/uid/TP40001051-CH4-SW6\)
is:
> “static” methods and properties are now allowed in classes (as an alias for class final). You are now allowed to declare static stored properties in classes, which have global storage and are lazily initialized on first access (like global variables). Protocols now declare type requirements as static requirements instead of declaring them as class requirements. (17198298)

If even the Swift team itself has difficulties in picking one from the
two and had to revert its initial decision after several revisions, we
know these keywords are indeed confusing.

So now protocols use `static` to declare type methods, when a class
adapts such protocols, should it implement those static methods, as
static methods or class methods?

But static means final, right? Does it mean we can not override these
methods in subclasses of the conforming class?

These kinds of unnecessary confusion and hesitation should be
resolved, and could if this proposal is implemented.

### Unnecessary and inconsistent differentiation

The `class` keyword is only used in classes. In the current
implementation of Swift the differences between `class` and `static`
are:

1. Class properties can only be calculated properties but not stored properties.
2. Class methods(also calculated properties) are dynamically
dispatched while static ones are statically dispatched.

If we can eliminate the differences or find better ways to
differentiate we can use one unified keyword instead for declaring
type properties and methods.

Let’s see.

#### Class stored properties VS. static stored properties

If you use the `class` keyword to declare a stored property in a class
you will get this compiling error:
> class stored properties not yet supported in classes; did you mean 'static'?

So what are class stored properties? How are they different from
static stored properties?

As far as I know, class stored properties, if ever implemented in
Swift, “would be what Ruby calls ‘class instance
variables’”.<sup>[1](https://twitter.com/UINT_MIN/status/584104757117095936\)</sup>

So what are class instance variables?

The best explanation I can find is this
[one](http://martinfowler.com/bliki/ClassInstanceVariable.html\) from
Martin Fowler.

Do we really want this feature in Swift? “If we didn't already have
these, would we add them to Swift 3?"

I strongly believe we won’t add it to Swift 3. Actually I believe we
will never add it to Swift, because its use cases are so rare which is
also why it hasn’t been implemented so far in Swift.

If we agree we are not going to support class stored properties, there
is and will be only one kind of stored properties for types and we
only need one keyword to declare such properties.

#### Class methods VS. static methods

*Since calculated properties are also methods in essence they are also
covered by this section.*

The only difference is how methods are dispatched.

Let’s see [how we handle it for instance
methods](Increasing Performance by Reducing Dynamic Dispatch - Swift Blog - Apple Developer <Increasing Performance by Reducing Dynamic Dispatch - Swift Blog - Apple Developer):

* Methods are overridable hence dynamically dispatched by default.
* In performance critical code use these techniques to restrict this
dynamic behavior when it isn’t needed to improve performance:

    1. Use the `final` keyword when we know that a declaration does
not need to be overridden.
    2. Infer `final` on declarations referenced in one file by
applying the `private` keyword.
    3. Use `Whole Module Optimization` to infer `final` on `internal`
declarations.

So why abandon this whole system to use another totally different one
for differentiating `static dispatch` and `dynamic dispatch` for type
methods?

If we reuse this system for type methods, not only can we have a
consistent design for both instance and type methods, but also we can
get rid of the last place where two keywords for type member
declarations are needed.

## Proposed solution

1. Use the keyword `type` to declare type properties and methods.
2. Type properties and methods are overridable hence dynamically
dispatched by default. Use the `final` keyword or inferred `final` to
make them final and statically dispatched, just like instance
properties and methods.
3. Type properties can be stored or calculated, just like instance properties.

As you can see, it is a very simple and elegant design:

* Just a single keyword `type` to differentiate type member
declarations from instance member declarations. `type` is a good
keyword because:

    1. It is consistent with the wording of the concepts of `type
properties` and `type methods`.
    2. It is never used as a keyword before in Swift, Objective-C or
C. There will be no conflicts or overloading of it meanings.
* Except for that, how things are declared, differentiated and
optimized are exactly the same in both type and instance world. Very
consistent.

## Comparison with current design

* Dynamic Dispatch VS. Static Dispatch

// Old
class Foo {
    func dynamicInstanceMethod() {}
    final func staticInstanceMethod() {}

    class func dynamicTypeMethod() {}
    static func staticTypeMethod() {}
}
// New
class Foo {
    func dynamicInstanceMethod() {}
    final func staticInstanceMethod() {}

    type func dynamicTypeMethod() {}
    final type func staticTypeMethod() {}
}

* Stored Properties VS. Calculated Properties

// Old
class Bar {
    static let i = 1

    class var j: Int {
        return 1
    }
}
// New
class Bar {
    type let i = 1

    type var j: Int {
        return 1
    }
}

* Struct Implementation VS. Class Implementation of Protocol

// Old
protocol P {
    static func foo()
}

struct S: P {
    static func foo() {}
}

class C: P {
    class func foo() {}
}
// New
protocol P {
    type func foo()
}

struct S: P {
    type func foo() {}
}

class C: P {
    type func foo() {}
}

## Impact on existing code

With the help of a good migration tool, there will be no impact on
existing code at all. And the migration rules are very clear and
simple:

* Map `static` to `type` in protocols.
* Map `static` to `type` in structs and enums.
* Map `class` to `type` and `static` to `final type` in classes.

One concern I can think of is: because type methods are dynamically
dispatched by default in the new design, will we forget to do the
`final` optimization so the general performance of Swift code become
worse?

I think it is probably true. But we also forget to do the `final`
optimization for instance methods from time to time. Since there are
way more instance methods than type methods in most code the
performance impact will be very small. Maybe this change is a good
opportunity to remind us to do the `final` optimization for instance
methods thus even results in a better general performance.

And don’t forget we have the tools to automatically infer `final` for
us in many cases if we write the proper code and use the proper
compiler features.

After all, it is mainly on us to write good code to produce good final
products. If the system is consistent we’ll have better chances to
master it and use it properly.

## Alternatives considered

Alternatively we could:
* Keep using `static` and `class` keywords.
* Keep the confusion when implementing `static` protocol requirements
using `class` properties and methods in conforming classes.
* Keep the inconsistency between type member declarations and instance
member declarations.
* Keep overloading meanings on the `static` keyword that is already
historically overloaded in C and Objective-C with which Swift must mix
and match.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

static means something like 9 different things in C, including the little known C99 static array parameter size use. That said, it is not overloaded in swift, and its use in Java and C# is very similar to that in Swift. Further, again, I have not heard of any problems in practice with the use of the static keyword here.

-Chris

···

On Dec 8, 2015, at 7:51 AM, Ling Wang via swift-evolution <swift-evolution@swift.org> wrote:

Yes, the `static` is badly overloaded with many different meanings:
1. static storage (old, from C)
2. static linking (old, from C)
3. final (new in Swift)

This is a legit concern that I didn’t consider before.

I think there are several options, from the most general to the most subtle:
1. Stored type properties are implicit `final`, so behave exactly the same as the current static stored properties.
2. Stored type vars are implicit `final`, as you suggested, so behave exactly the same as the current static stored vars. All other type properties(including stored type lets) are normally overridable.
3. Store type vars are overridable but can not be observed.

There could be a even more subtle option if my understanding of how classes exist in runtime is correct.

In my understanding, classes exist as singleton instances of their meta classes. If it is true, which I believe is the image in most people’s heads if they know about meta classes, then the class objects tree is exactly the same as the class hierarchy tree. Every subclass object contains(or points to) its super class object in its layout. The super class part is shared by all subclass objects and the super class object per se. So stored type properties are conceptually and naturally shared by the super class and all its subclasses, which behave exactly like the current static stored properties.

In this modal, the 4th option is:
4. Stored type vars are overridable and observable. When they are assigned new values, all their property observers defined in the class hierarchy are called, calling order is not significant, the reason of which will be addressed later.

Unfortunately, there is one last catch: if more than one classes assign a value to the property within their didSet observer, the final result is undefined.

This issue can not even be resolved by ordering observer calls from top to bottom in the class hierarchy because we can not meaningfully define the order within the same level if there are more than one subclasses in it.

So one addition to option 4:
4-1. Stored type vars’ didSet observers are not allowed to reassign value to the observed property.

But it is such a corner case that probably this limitation is acceptable.

What do you think? Is my understanding of class objects correct? Which option do you like best?

- Ling

···

On Dec 8, 2015, at 5:40 PM, Jordan Rose <jordan_rose@apple.com> wrote:

On Dec 7, 2015, at 19:12, Ling Wang via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Besides, we shouldn’t use `final` to denote storage at all for `final` is about inheritability/overridability not about storage.

Please remember that stored properties can be overridden in Swift:

class Base {
  /*instance*/ var flag: Bool = true
}

class Sub : Base {
  override var flag: Bool {
    didSet {
      if flag { print("The flag was set!") }
    }
  }
}

This is theoretically possible at the class level as well, but doesn't really make sense for what's currently spelled "static var", since you'd be accessing the same storage in different ways. Does the proposal mean that a stored "type var" is non-overrideable, but a computed "type var" is overrideable, implicitly?

Jordan

Can you explain the inconsistency between the semantics of “type var” and “type func”?

I don’t see any inconsistency:
1. For calculated properties, “type var” and “type func” are essentially the same thing. My proposal doesn’t treat them differently.
2. For stored properties, “type var” and “type func” are totally different things, by definition. One is data, one is function. It is the same for instance properties and methods. This difference is inherent in object-orientated programming.

- Ling

···

On Dec 9, 2015, at 12:01 AM, Chris Lattner <clattner@apple.com> wrote:

On Dec 7, 2015, at 7:12 PM, Ling Wang via swift-evolution <swift-evolution@swift.org> wrote:

Now I understand your concerns. But you misunderstood my proposal. I'll restate my points about “type properties”:

1. Stored class properties(let’s call them “class instance variables” for better discussion about “stored type properties” below) are not very useful or needed. So we are not likely to add them to Swift. This one we both agree. So there is only one kind of stored properties for types and they are stored like global variables, which are now called “static stored properties“.

2. `type` properties in my proposal covers both stored properties and calculated properties. Except for the `type` keyword, the way they are declared are exactly the same as that of instance properties:

class Foo {
   type let i = 1 // stored type property
   type var k: Int { // calculated type property
       return 1
   }
} 

3. Since we’ve already excluded “class instance variables” in point 1, stored type properies in my proposal are certainly not “class instance variables”. They behave the same as the current “static stored properties”. This is where you misunderstood me.

So you don’t need the `final` keyword to make them “static”. If they are “stored”(VS calculated) they are “static”. We just don’t use `static` as the keyword.

Static storage is the implementation details. Just like global variable declarations don’t need `static` keyword though they use static storage, stored type property declarations don’t need `static` keyword to denote they use static storage. After all there is only one kind of stored type properties.

The problem is one of consistency. It would be very problematic for a “type var” to have one set of semantics, but a “type func” to have completely different semantics. Also keep in mind that we *do* have *computed* static and computed class properties, today.

-Chris

I understand the intention to keep total compatibility with existing code. But it probably doesn’t deserve a new keyword just for that since "final by default" is really not so important performance-wise: https://github.com/an0/swift-evolution/blob/master/proposals/NNNN-unify-static-and-class-keywords.md#impact-on-existing-code\.

···

On Dec 8, 2015, at 10:44 AM, Daniel Valls Estella <daniel@upzzle.com> wrote:

`overridable` is unnecessary since we already have `final`.

Agree in part, but it’s to keep the current behaviour of being final by default, without anotating it, that maybe is a better aproach for shared properties.

El 8 des 2015, a les 16:51, Ling Wang <an00na@gmail.com <mailto:an00na@gmail.com>> va escriure:

Yes, the `static` is badly overloaded with many different meanings:
1. static storage (old, from C)
2. static linking (old, from C)
3. final (new in Swift)

That’s why I’m proposing we use a new keyword. My initial suggestion is `type` but I welcome any better alternative.

On Dec 8, 2015, at 7:33 AM, Daniel Valls Estella <daniel@upzzle.com <mailto:daniel@upzzle.com>> wrote:

Just if it helps someway, in my opinion:

- static is well known keyword modifier from long ago, but I think is an unfortunate one because is named that way from a complier point fo view, not from a language programmer user.

- I don’t understand static as having an implicit final behaviour.

- It seems we want to mix in one word parallel variables modifiers when is not a goal reduce code typing.

- I found confusing using class keyword instead of static just to note that a static computed variable is not final (same for methods). More when the language provides the final keyword to identify this behaviour.

- why not ?

class SomeClass {

    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 27
    }
    static final var nonOverrideableComputedTypeProperty: Int {
        return 107
    }
}

-But as I mentioned I think static is not a good keyword, only we have been used to it.

Maybe shared ? Adding overridable in case?

class SomeClass {
    shared var storedTypeProperty = “Some value."
    shared var computedTypeProperty: Int {
        return 27
    }
    shared overridable var overrideableComputedTypeProperty: Int {
        return 107
    }
}

Or:

class SomeClass {
    shared var storedTypeProperty = “Some value."
    shared var computedTypeProperty: Int {
        return 27
    }
    shared final var nonOverrideableComputedTypeProperty: Int {
        return 107
    }
}

Thanks,

Daniel

Fragment de: Apple Inc. “The Swift Programming Language (Swift 2.2)“. iBooks.

Fragment de: Apple Inc. “The Swift Programming Language (Swift 2.2)“. iBooks.

El 8 des 2015, a les 5:22, J. Cheyo Jimenez via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> va escriure:

Hi Ling,

In April 2015 you said on your blog that "I was not convinced so I filed an radar." It would seem to me that you are not convinced now either, even after Chris explained that what you are asking for was implemented, reverted and ultimately rejected. I appreciate the fact that you are thinking and worry about the apparent inconstancy. I rather the swift swift team spend more time focusing on ABI stability than on non issue items. Swift is young. Who knows maybe your ideas will make it in a future version of Swift.

wangling.me/2015/04/unify-type-properties-and-methods.html <http://wangling.me/2015/04/unify-type-properties-and-methods.html&gt;
Apple Developer Forums

On Monday, December 7, 2015, an0 <an00na@gmail.com <mailto:an00na@gmail.com>> wrote:
I read that. But that's a long time ago, Swift has evolved a lot since then. I believe the Swift team may have some new ideas about it or at least could take a look at the ideas in this proposal.

Do you have any ideas of your own about this proposal? I'd really like to learn:)

On Mon, Dec 7, 2015 at 12:49 PM J. Cheyo Jimenez <cheyo@masters3d.com <javascript:_e(%7B%7D,'cvml','cheyo@masters3d.com');>> wrote:
ChrisLattner wrote:

We considered unifying the syntax (e.g. using "type" as the keyword), but that doesn't actually simply things. The keywords "class" and "static" are good for familiarity and are quite descriptive (once you understand how + methods work), and open the door for potentially adding truly static methods to classes. The primary weirdness of this model is that protocols have to pick a keyword (and we chose "class"), but on balance it is the right tradeoff.

-Chris
Jul 5, 2014

Apple Developer Forums

On Monday, December 7, 2015, an0 via swift-evolution <swift-evolution@swift.org <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:
The idea is simple but the reasoning is long. So please bear with me.
You can read on github for a better reading experience:
https://github.com/an0/swift-evolution/blob/master/proposals/NNNN-unify-static-and-class-keywords.md\.

## Introduction

The coexistence of `static` and `class` keywords for declaring type
properties and methods is confusing and causes inconsistency between
type and instance member declarations. This document reasons why we
don’t need both and suggests we unify them with a better keyword
`type`.

## Motivation

### Confusion

One “language enhancement” of [Swift
1.2](https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc6_release_notes.html#//apple_ref/doc/uid/TP40001051-CH4-SW6\)
is:
> “static” methods and properties are now allowed in classes (as an alias for class final). You are now allowed to declare static stored properties in classes, which have global storage and are lazily initialized on first access (like global variables). Protocols now declare type requirements as static requirements instead of declaring them as class requirements. (17198298)

If even the Swift team itself has difficulties in picking one from the
two and had to revert its initial decision after several revisions, we
know these keywords are indeed confusing.

So now protocols use `static` to declare type methods, when a class
adapts such protocols, should it implement those static methods, as
static methods or class methods?

But static means final, right? Does it mean we can not override these
methods in subclasses of the conforming class?

These kinds of unnecessary confusion and hesitation should be
resolved, and could if this proposal is implemented.

### Unnecessary and inconsistent differentiation

The `class` keyword is only used in classes. In the current
implementation of Swift the differences between `class` and `static`
are:

1. Class properties can only be calculated properties but not stored properties.
2. Class methods(also calculated properties) are dynamically
dispatched while static ones are statically dispatched.

If we can eliminate the differences or find better ways to
differentiate we can use one unified keyword instead for declaring
type properties and methods.

Let’s see.

#### Class stored properties VS. static stored properties

If you use the `class` keyword to declare a stored property in a class
you will get this compiling error:
> class stored properties not yet supported in classes; did you mean 'static'?

So what are class stored properties? How are they different from
static stored properties?

As far as I know, class stored properties, if ever implemented in
Swift, “would be what Ruby calls ‘class instance
variables’”.<sup>[1](https://twitter.com/UINT_MIN/status/584104757117095936\)</sup>

So what are class instance variables?

The best explanation I can find is this
[one](http://martinfowler.com/bliki/ClassInstanceVariable.html\) from
Martin Fowler.

Do we really want this feature in Swift? “If we didn't already have
these, would we add them to Swift 3?"

I strongly believe we won’t add it to Swift 3. Actually I believe we
will never add it to Swift, because its use cases are so rare which is
also why it hasn’t been implemented so far in Swift.

If we agree we are not going to support class stored properties, there
is and will be only one kind of stored properties for types and we
only need one keyword to declare such properties.

#### Class methods VS. static methods

*Since calculated properties are also methods in essence they are also
covered by this section.*

The only difference is how methods are dispatched.

Let’s see [how we handle it for instance
methods](Increasing Performance by Reducing Dynamic Dispatch - Swift Blog - Apple Developer <Increasing Performance by Reducing Dynamic Dispatch - Swift Blog - Apple Developer):

* Methods are overridable hence dynamically dispatched by default.
* In performance critical code use these techniques to restrict this
dynamic behavior when it isn’t needed to improve performance:

    1. Use the `final` keyword when we know that a declaration does
not need to be overridden.
    2. Infer `final` on declarations referenced in one file by
applying the `private` keyword.
    3. Use `Whole Module Optimization` to infer `final` on `internal`
declarations.

So why abandon this whole system to use another totally different one
for differentiating `static dispatch` and `dynamic dispatch` for type
methods?

If we reuse this system for type methods, not only can we have a
consistent design for both instance and type methods, but also we can
get rid of the last place where two keywords for type member
declarations are needed.

## Proposed solution

1. Use the keyword `type` to declare type properties and methods.
2. Type properties and methods are overridable hence dynamically
dispatched by default. Use the `final` keyword or inferred `final` to
make them final and statically dispatched, just like instance
properties and methods.
3. Type properties can be stored or calculated, just like instance properties.

As you can see, it is a very simple and elegant design:

* Just a single keyword `type` to differentiate type member
declarations from instance member declarations. `type` is a good
keyword because:

    1. It is consistent with the wording of the concepts of `type
properties` and `type methods`.
    2. It is never used as a keyword before in Swift, Objective-C or
C. There will be no conflicts or overloading of it meanings.
* Except for that, how things are declared, differentiated and
optimized are exactly the same in both type and instance world. Very
consistent.

## Comparison with current design

* Dynamic Dispatch VS. Static Dispatch

// Old
class Foo {
    func dynamicInstanceMethod() {}
    final func staticInstanceMethod() {}

    class func dynamicTypeMethod() {}
    static func staticTypeMethod() {}
}
// New
class Foo {
    func dynamicInstanceMethod() {}
    final func staticInstanceMethod() {}

    type func dynamicTypeMethod() {}
    final type func staticTypeMethod() {}
}

* Stored Properties VS. Calculated Properties

// Old
class Bar {
    static let i = 1

    class var j: Int {
        return 1
    }
}
// New
class Bar {
    type let i = 1

    type var j: Int {
        return 1
    }
}

* Struct Implementation VS. Class Implementation of Protocol

// Old
protocol P {
    static func foo()
}

struct S: P {
    static func foo() {}
}

class C: P {
    class func foo() {}
}
// New
protocol P {
    type func foo()
}

struct S: P {
    type func foo() {}
}

class C: P {
    type func foo() {}
}

## Impact on existing code

With the help of a good migration tool, there will be no impact on
existing code at all. And the migration rules are very clear and
simple:

* Map `static` to `type` in protocols.
* Map `static` to `type` in structs and enums.
* Map `class` to `type` and `static` to `final type` in classes.

One concern I can think of is: because type methods are dynamically
dispatched by default in the new design, will we forget to do the
`final` optimization so the general performance of Swift code become
worse?

I think it is probably true. But we also forget to do the `final`
optimization for instance methods from time to time. Since there are
way more instance methods than type methods in most code the
performance impact will be very small. Maybe this change is a good
opportunity to remind us to do the `final` optimization for instance
methods thus even results in a better general performance.

And don’t forget we have the tools to automatically infer `final` for
us in many cases if we write the proper code and use the proper
compiler features.

After all, it is mainly on us to write good code to produce good final
products. If the system is consistent we’ll have better chances to
master it and use it properly.

## Alternatives considered

Alternatively we could:
* Keep using `static` and `class` keywords.
* Keep the confusion when implementing `static` protocol requirements
using `class` properties and methods in conforming classes.
* Keep the inconsistency between type member declarations and instance
member declarations.
* Keep overloading meanings on the `static` keyword that is already
historically overloaded in C and Objective-C with which Swift must mix
and match.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

`static` at least has two meanings in Swift:
1. It means `final` for type methods.
2. It also means static storage for stored type properties.

But Swift must mix and match with Objective-C and C so all the existing meanings in these two languages are also inherited in Swift.

Yes, if we all either don’t use it or get used to its usage we won’t feel the design flaws because we won’t think about it. But if we step back and think carefully about it at the design level, we should be able to see the issues. As you advocate in several other proposals like removing ++/— and removing C for-loop, if we have opportunities to do things better in Swift we should do them even if they break old conventions and assumptions.

Also, consider how totally new programmers will feel. I believe they will feel the overloading of meanings on `static`, the dichotomy of static and class methods especially when implementing a static requirement from a protocol, the inconsistency between class and instance member declarations.

- Ling

···

On Dec 8, 2015, at 11:37 PM, Chris Lattner <clattner@apple.com> wrote:

On Dec 8, 2015, at 7:51 AM, Ling Wang via swift-evolution <swift-evolution@swift.org> wrote:

Yes, the `static` is badly overloaded with many different meanings:
1. static storage (old, from C)
2. static linking (old, from C)
3. final (new in Swift)

static means something like 9 different things in C, including the little known C99 static array parameter size use. That said, it is not overloaded in swift, and its use in Java and C# is very similar to that in Swift. Further, again, I have not heard of any problems in practice with the use of the static keyword here.

-Chris

When verifying my class object modal I actually found one issue of the current class property observers.

In the current implementation, when super class’s class property setter is called, subclasses’ observers don’t get called. But after the call of super setter, the value of this property accessed via subclasses(suppose them don’t overload get/set) does change. It means their properties are changed without their knowing it even though they explicitly define observers to observe the changes.

var backingVarForFooI = 0

class Foo {
    class var i: Int {
        get {
            return backingVarForFooI
        }
        
        set {
            backingVarForFooI = newValue
            print("Foo.i.set \(newValue)")
        }
    }
}

class Bar: Foo {
    override class var i: Int {
        didSet {
            print("Bar.i.didSet \(i)")
        }
    }
}

print(Bar.i)
Foo.i = 3
print(Bar.i)

If we think about it, it doesn’t matter whether the proper is stored or calculated. Storage is just the implementation details, it doesn’t affect the interface or the concept. Besides, even calculated properties need storage if they are mutable.

After super class changes a property, people expect to get the changed value when they access the property via their subclasses(suppose they don’t overload get/set) and expect the corresponding observers to get called. So the class object modal that I speculated sharing properties among all subclasses and super class and notifying them about property changes is the only sound modal in this aspect. So the concern about overloading stored type properties with observers is not only about stored type properties but about all type properties.

So there is nothing special to separate stored type properties from calculated type properties. It supports my proposal to unite them under a more general keyword.

- Ling

···

On Dec 9, 2015, at 10:23 AM, Ling Wang <an00na@gmail.com> wrote:

This is a legit concern that I didn’t consider before.

I think there are several options, from the most general to the most subtle:
1. Stored type properties are implicit `final`, so behave exactly the same as the current static stored properties.
2. Stored type vars are implicit `final`, as you suggested, so behave exactly the same as the current static stored vars. All other type properties(including stored type lets) are normally overridable.
3. Store type vars are overridable but can not be observed.

There could be a even more subtle option if my understanding of how classes exist in runtime is correct.

In my understanding, classes exist as singleton instances of their meta classes. If it is true, which I believe is the image in most people’s heads if they know about meta classes, then the class objects tree is exactly the same as the class hierarchy tree. Every subclass object contains(or points to) its super class object in its layout. The super class part is shared by all subclass objects and the super class object per se. So stored type properties are conceptually and naturally shared by the super class and all its subclasses, which behave exactly like the current static stored properties.

In this modal, the 4th option is:
4. Stored type vars are overridable and observable. When they are assigned new values, all their property observers defined in the class hierarchy are called, calling order is not significant, the reason of which will be addressed later.

Unfortunately, there is one last catch: if more than one classes assign a value to the property within their didSet observer, the final result is undefined.

This issue can not even be resolved by ordering observer calls from top to bottom in the class hierarchy because we can not meaningfully define the order within the same level if there are more than one subclasses in it.

So one addition to option 4:
4-1. Stored type vars’ didSet observers are not allowed to reassign value to the observed property.

But it is such a corner case that probably this limitation is acceptable.

What do you think? Is my understanding of class objects correct? Which option do you like best?

- Ling

On Dec 8, 2015, at 5:40 PM, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

On Dec 7, 2015, at 19:12, Ling Wang via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Besides, we shouldn’t use `final` to denote storage at all for `final` is about inheritability/overridability not about storage.

Please remember that stored properties can be overridden in Swift:

class Base {
  /*instance*/ var flag: Bool = true
}

class Sub : Base {
  override var flag: Bool {
    didSet {
      if flag { print("The flag was set!") }
    }
  }
}

This is theoretically possible at the class level as well, but doesn't really make sense for what's currently spelled "static var", since you'd be accessing the same storage in different ways. Does the proposal mean that a stored "type var" is non-overrideable, but a computed "type var" is overrideable, implicitly?

Jordan

The current behavior is not a bug; it matches the behavior for instance computed properties. To put it another way, if the base class's computed implementation stored values in a dictionary keyed by 'self', it would effectively be an implementation of true class properties. (People do indeed do this in Objective-C, although it's not common.)

We definitely don't want setting a base class property to invoke an arbitrary number of arbitrarily-ordered observers. Moreover, what if some of the subclasses actually override the setter entirely, instead of just adding an observer? That's clearly not implementable.

Again, I'm not saying you/we can't pick a behavior and stick with it. I just want the tradeoffs to be clear.

Jordan

···

On Dec 10, 2015, at 7:23, Ling Wang <an00na@gmail.com> wrote:

When verifying my class object modal I actually found one issue of the current class property observers.

In the current implementation, when super class’s class property setter is called, subclasses’ observers don’t get called. But after the call of super setter, the value of this property accessed via subclasses(suppose them don’t overload get/set) does change. It means their properties are changed without their knowing it even though they explicitly define observers to observe the changes.

var backingVarForFooI = 0

class Foo {
    class var i: Int {
        get {
            return backingVarForFooI
        }
       
        set {
            backingVarForFooI = newValue
            print("Foo.i.set \(newValue)")
        }
    }
}

class Bar: Foo {
    override class var i: Int {
        didSet {
            print("Bar.i.didSet \(i)")
        }
    }
}

print(Bar.i)
Foo.i = 3
print(Bar.i)

If we think about it, it doesn’t matter whether the proper is stored or calculated. Storage is just the implementation details, it doesn’t affect the interface or the concept. Besides, even calculated properties need storage if they are mutable.

After super class changes a property, people expect to get the changed value when they access the property via their subclasses(suppose they don’t overload get/set) and expect the corresponding observers to get called. So the class object modal that I speculated sharing properties among all subclasses and super class and notifying them about property changes is the only sound modal in this aspect. So the concern about overloading stored type properties with observers is not only about stored type properties but about all type properties.

So there is nothing special to separate stored type properties from calculated type properties. It supports my proposal to unite them under a more general keyword.

- Ling

On Dec 9, 2015, at 10:23 AM, Ling Wang <an00na@gmail.com <mailto:an00na@gmail.com>> wrote:

This is a legit concern that I didn’t consider before.

I think there are several options, from the most general to the most subtle:
1. Stored type properties are implicit `final`, so behave exactly the same as the current static stored properties.
2. Stored type vars are implicit `final`, as you suggested, so behave exactly the same as the current static stored vars. All other type properties(including stored type lets) are normally overridable.
3. Store type vars are overridable but can not be observed.

There could be a even more subtle option if my understanding of how classes exist in runtime is correct.

In my understanding, classes exist as singleton instances of their meta classes. If it is true, which I believe is the image in most people’s heads if they know about meta classes, then the class objects tree is exactly the same as the class hierarchy tree. Every subclass object contains(or points to) its super class object in its layout. The super class part is shared by all subclass objects and the super class object per se. So stored type properties are conceptually and naturally shared by the super class and all its subclasses, which behave exactly like the current static stored properties.

In this modal, the 4th option is:
4. Stored type vars are overridable and observable. When they are assigned new values, all their property observers defined in the class hierarchy are called, calling order is not significant, the reason of which will be addressed later.

Unfortunately, there is one last catch: if more than one classes assign a value to the property within their didSet observer, the final result is undefined.

This issue can not even be resolved by ordering observer calls from top to bottom in the class hierarchy because we can not meaningfully define the order within the same level if there are more than one subclasses in it.

So one addition to option 4:
4-1. Stored type vars’ didSet observers are not allowed to reassign value to the observed property.

But it is such a corner case that probably this limitation is acceptable.

What do you think? Is my understanding of class objects correct? Which option do you like best?

- Ling

On Dec 8, 2015, at 5:40 PM, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

On Dec 7, 2015, at 19:12, Ling Wang via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Besides, we shouldn’t use `final` to denote storage at all for `final` is about inheritability/overridability not about storage.

Please remember that stored properties can be overridden in Swift:

class Base {
  /*instance*/ var flag: Bool = true
}

class Sub : Base {
  override var flag: Bool {
    didSet {
      if flag { print("The flag was set!") }
    }
  }
}

This is theoretically possible at the class level as well, but doesn't really make sense for what's currently spelled "static var", since you'd be accessing the same storage in different ways. Does the proposal mean that a stored "type var" is non-overrideable, but a computed "type var" is overrideable, implicitly?

Jordan

I just realized that I wrote `overload` when I meant `override` in some places. Sorry for that.

I didn’t say it is a bug, just an issue. An issue like I only get notified when I draw money from the bank account I inherited from my father but not when my father draw from it. :p

The underlying implementation may match match that for instance computed properties. But we can't demonstrate this behavior on instance properties, can we? How can a Swift user trigger super setter without triggering subclass observer when writing to an instance property?

There is no clear solution to overriding setter and overriding with observer at the same time.

When I talked about the issue, my major point is that there is no necessary and meaningful difference between stored and calculated type properties, even the issues are the same, so we can unite them with a single keyword.

I thought I got it from your first mail, but after these discussion I got lost:( What exactly is your concern of stored type properties from my proposal? Why doesn't it apply to calculated type properties?

- Ling

···

On Dec 10, 2015, at 12:17 PM, Jordan Rose <jordan_rose@apple.com> wrote:

The current behavior is not a bug; it matches the behavior for instance computed properties. To put it another way, if the base class's computed implementation stored values in a dictionary keyed by 'self', it would effectively be an implementation of true class properties. (People do indeed do this in Objective-C, although it's not common.)

We definitely don't want setting a base class property to invoke an arbitrary number of arbitrarily-ordered observers. Moreover, what if some of the subclasses actually override the setter entirely, instead of just adding an observer? That's clearly not implementable.

Again, I'm not saying you/we can't pick a behavior and stick with it. I just want the tradeoffs to be clear.

Jordan

On Dec 10, 2015, at 7:23, Ling Wang <an00na@gmail.com <mailto:an00na@gmail.com>> wrote:

When verifying my class object modal I actually found one issue of the current class property observers.

In the current implementation, when super class’s class property setter is called, subclasses’ observers don’t get called. But after the call of super setter, the value of this property accessed via subclasses(suppose them don’t overload get/set) does change. It means their properties are changed without their knowing it even though they explicitly define observers to observe the changes.

var backingVarForFooI = 0

class Foo {
    class var i: Int {
        get {
            return backingVarForFooI
        }
       
        set {
            backingVarForFooI = newValue
            print("Foo.i.set \(newValue)")
        }
    }
}

class Bar: Foo {
    override class var i: Int {
        didSet {
            print("Bar.i.didSet \(i)")
        }
    }
}

print(Bar.i)
Foo.i = 3
print(Bar.i)

If we think about it, it doesn’t matter whether the proper is stored or calculated. Storage is just the implementation details, it doesn’t affect the interface or the concept. Besides, even calculated properties need storage if they are mutable.

After super class changes a property, people expect to get the changed value when they access the property via their subclasses(suppose they don’t overload get/set) and expect the corresponding observers to get called. So the class object modal that I speculated sharing properties among all subclasses and super class and notifying them about property changes is the only sound modal in this aspect. So the concern about overloading stored type properties with observers is not only about stored type properties but about all type properties.

So there is nothing special to separate stored type properties from calculated type properties. It supports my proposal to unite them under a more general keyword.

- Ling

On Dec 9, 2015, at 10:23 AM, Ling Wang <an00na@gmail.com <mailto:an00na@gmail.com>> wrote:

This is a legit concern that I didn’t consider before.

I think there are several options, from the most general to the most subtle:
1. Stored type properties are implicit `final`, so behave exactly the same as the current static stored properties.
2. Stored type vars are implicit `final`, as you suggested, so behave exactly the same as the current static stored vars. All other type properties(including stored type lets) are normally overridable.
3. Store type vars are overridable but can not be observed.

There could be a even more subtle option if my understanding of how classes exist in runtime is correct.

In my understanding, classes exist as singleton instances of their meta classes. If it is true, which I believe is the image in most people’s heads if they know about meta classes, then the class objects tree is exactly the same as the class hierarchy tree. Every subclass object contains(or points to) its super class object in its layout. The super class part is shared by all subclass objects and the super class object per se. So stored type properties are conceptually and naturally shared by the super class and all its subclasses, which behave exactly like the current static stored properties.

In this modal, the 4th option is:
4. Stored type vars are overridable and observable. When they are assigned new values, all their property observers defined in the class hierarchy are called, calling order is not significant, the reason of which will be addressed later.

Unfortunately, there is one last catch: if more than one classes assign a value to the property within their didSet observer, the final result is undefined.

This issue can not even be resolved by ordering observer calls from top to bottom in the class hierarchy because we can not meaningfully define the order within the same level if there are more than one subclasses in it.

So one addition to option 4:
4-1. Stored type vars’ didSet observers are not allowed to reassign value to the observed property.

But it is such a corner case that probably this limitation is acceptable.

What do you think? Is my understanding of class objects correct? Which option do you like best?

- Ling

On Dec 8, 2015, at 5:40 PM, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

On Dec 7, 2015, at 19:12, Ling Wang via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Besides, we shouldn’t use `final` to denote storage at all for `final` is about inheritability/overridability not about storage.

Please remember that stored properties can be overridden in Swift:

class Base {
  /*instance*/ var flag: Bool = true
}

class Sub : Base {
  override var flag: Bool {
    didSet {
      if flag { print("The flag was set!") }
    }
  }
}

This is theoretically possible at the class level as well, but doesn't really make sense for what's currently spelled "static var", since you'd be accessing the same storage in different ways. Does the proposal mean that a stored "type var" is non-overrideable, but a computed "type var" is overrideable, implicitly?

Jordan

Here is your code, minus the "class" qualifier.

var backingVarForFooI = 0

class Foo {
    var i: Int { // was "class"
        get {
            return backingVarForFooI
        }
        
        set {
            backingVarForFooI = newValue
            print("Foo.i.set \(newValue)")
        }
    }
}

class Bar: Foo {
    override var i: Int { // was "class"
        didSet {
            print("Bar.i.didSet \(i)")
        }
    }
}

print(Bar.i)
Foo.i = 3
print(Bar.i)

Now, clearly this is rather silly code, but my point is "if you choose to use a global variable as the backing storage of a computed property, you can mutate it in multiple ways". Whether the computed property is a class property or an instance property doesn't affect that.

That's not an argument against unifying "class" and "static". It's just pointing out that the existing behavior of computed class variables isn't an argument for unifying "class" and "static" either.

Jordan

···

On Dec 10, 2015, at 12:19, Ling Wang <an00na@gmail.com> wrote:

I just realized that I wrote `overload` when I meant `override` in some places. Sorry for that.

I didn’t say it is a bug, just an issue. An issue like I only get notified when I draw money from the bank account I inherited from my father but not when my father draw from it. :p

The underlying implementation may match match that for instance computed properties. But we can't demonstrate this behavior on instance properties, can we? How can a Swift user trigger super setter without triggering subclass observer when writing to an instance property?

There is no clear solution to overriding setter and overriding with observer at the same time.

When I talked about the issue, my major point is that there is no necessary and meaningful difference between stored and calculated type properties, even the issues are the same, so we can unite them with a single keyword.

I thought I got it from your first mail, but after these discussion I got lost:( What exactly is your concern of stored type properties from my proposal? Why doesn't it apply to calculated type properties?

- Ling

On Dec 10, 2015, at 12:17 PM, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

The current behavior is not a bug; it matches the behavior for instance computed properties. To put it another way, if the base class's computed implementation stored values in a dictionary keyed by 'self', it would effectively be an implementation of true class properties. (People do indeed do this in Objective-C, although it's not common.)

We definitely don't want setting a base class property to invoke an arbitrary number of arbitrarily-ordered observers. Moreover, what if some of the subclasses actually override the setter entirely, instead of just adding an observer? That's clearly not implementable.

Again, I'm not saying you/we can't pick a behavior and stick with it. I just want the tradeoffs to be clear.

Jordan

On Dec 10, 2015, at 7:23, Ling Wang <an00na@gmail.com <mailto:an00na@gmail.com>> wrote:

When verifying my class object modal I actually found one issue of the current class property observers.

In the current implementation, when super class’s class property setter is called, subclasses’ observers don’t get called. But after the call of super setter, the value of this property accessed via subclasses(suppose them don’t overload get/set) does change. It means their properties are changed without their knowing it even though they explicitly define observers to observe the changes.

var backingVarForFooI = 0

class Foo {
    class var i: Int {
        get {
            return backingVarForFooI
        }
       
        set {
            backingVarForFooI = newValue
            print("Foo.i.set \(newValue)")
        }
    }
}

class Bar: Foo {
    override class var i: Int {
        didSet {
            print("Bar.i.didSet \(i)")
        }
    }
}

print(Bar.i)
Foo.i = 3
print(Bar.i)

If we think about it, it doesn’t matter whether the proper is stored or calculated. Storage is just the implementation details, it doesn’t affect the interface or the concept. Besides, even calculated properties need storage if they are mutable.

After super class changes a property, people expect to get the changed value when they access the property via their subclasses(suppose they don’t overload get/set) and expect the corresponding observers to get called. So the class object modal that I speculated sharing properties among all subclasses and super class and notifying them about property changes is the only sound modal in this aspect. So the concern about overloading stored type properties with observers is not only about stored type properties but about all type properties.

So there is nothing special to separate stored type properties from calculated type properties. It supports my proposal to unite them under a more general keyword.

- Ling

On Dec 9, 2015, at 10:23 AM, Ling Wang <an00na@gmail.com <mailto:an00na@gmail.com>> wrote:

This is a legit concern that I didn’t consider before.

I think there are several options, from the most general to the most subtle:
1. Stored type properties are implicit `final`, so behave exactly the same as the current static stored properties.
2. Stored type vars are implicit `final`, as you suggested, so behave exactly the same as the current static stored vars. All other type properties(including stored type lets) are normally overridable.
3. Store type vars are overridable but can not be observed.

There could be a even more subtle option if my understanding of how classes exist in runtime is correct.

In my understanding, classes exist as singleton instances of their meta classes. If it is true, which I believe is the image in most people’s heads if they know about meta classes, then the class objects tree is exactly the same as the class hierarchy tree. Every subclass object contains(or points to) its super class object in its layout. The super class part is shared by all subclass objects and the super class object per se. So stored type properties are conceptually and naturally shared by the super class and all its subclasses, which behave exactly like the current static stored properties.

In this modal, the 4th option is:
4. Stored type vars are overridable and observable. When they are assigned new values, all their property observers defined in the class hierarchy are called, calling order is not significant, the reason of which will be addressed later.

Unfortunately, there is one last catch: if more than one classes assign a value to the property within their didSet observer, the final result is undefined.

This issue can not even be resolved by ordering observer calls from top to bottom in the class hierarchy because we can not meaningfully define the order within the same level if there are more than one subclasses in it.

So one addition to option 4:
4-1. Stored type vars’ didSet observers are not allowed to reassign value to the observed property.

But it is such a corner case that probably this limitation is acceptable.

What do you think? Is my understanding of class objects correct? Which option do you like best?

- Ling

On Dec 8, 2015, at 5:40 PM, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

On Dec 7, 2015, at 19:12, Ling Wang via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Besides, we shouldn’t use `final` to denote storage at all for `final` is about inheritability/overridability not about storage.

Please remember that stored properties can be overridden in Swift:

class Base {
  /*instance*/ var flag: Bool = true
}

class Sub : Base {
  override var flag: Bool {
    didSet {
      if flag { print("The flag was set!") }
    }
  }
}

This is theoretically possible at the class level as well, but doesn't really make sense for what's currently spelled "static var", since you'd be accessing the same storage in different ways. Does the proposal mean that a stored "type var" is non-overrideable, but a computed "type var" is overrideable, implicitly?

Jordan

But can your code compile and run? How can you access instance properties via class interface?
I didn't bring up this behavior of computed class variables as an argument for unifying "class" and "static". I brought up it to demonstrate the similarity between computed and stored type properties, even on limitation/issue level, which is an argument for unifying "class" and "static".

- Ling

···

_____________________________
From: Jordan Rose <jordan_rose@apple.com>
Sent: Thursday, December 10, 2015 7:06 PM
Subject: Re: [swift-evolution] Unify `static` and `class` keywords
To: Ling Wang <an00na@gmail.com>
Cc: swift-evolution <swift-evolution@swift.org>

          Here is your code, minus the "class" qualifier.
                var backingVarForFooI = 0
                   class Foo { var i: Int { // was "class" get { return backingVarForFooI } set { backingVarForFooI = newValue print("Foo.i.set \(newValue)") } } }
                   class Bar: Foo { override var i: Int { // was "class" didSet { print("Bar.i.didSet \(i)") } } }
                   print(Bar.i) Foo.i = 3 print(Bar.i)
       Now, clearly this is rather silly code, but my point is "if you choose to use a global variable as the backing storage of a computed property, you can mutate it in multiple ways". Whether the computed property is a class property or an instance property doesn't affect that.
       That's not an argument against unifying "class" and "static". It's just pointing out that the existing behavior of computed class variables isn't an argument for unifying "class" and "static" either.
       Jordan
    
              On Dec 10, 2015, at 12:19, Ling Wang < an00na@gmail.com> wrote:
                           I just realized that I wrote `overload` when I meant `override` in some places. Sorry for that.
      I didn’t say it is a bug, just an issue. An issue like I only get notified when I draw money from the bank account I inherited from my father but not when my father draw from it. :p
                   The underlying implementation may match match that for instance computed properties. But we can't demonstrate this behavior on instance properties, can we? How can a Swift user trigger super setter without triggering subclass observer when writing to an instance property?
                   There is no clear solution to overriding setter and overriding with observer at the same time.
                   When I talked about the issue, my major point is that there is no necessary and meaningful difference between stored and calculated type properties, even the issues are the same, so we can unite them with a single keyword.
I thought I got it from your first mail, but after these discussion I got lost:( What exactly is your concern of stored type properties from my proposal? Why doesn't it apply to calculated type properties?
       
               - Ling
                 
                                          On Dec 10, 2015, at 12:17 PM, Jordan Rose < jordan_rose@apple.com> wrote:
                                                              The current behavior is not a bug; it matches the behavior for instance computed properties. To put it another way, if the base class's computed implementation stored values in a dictionary keyed by 'self', it would effectively be an implementation of true class properties. (People do indeed do this in Objective-C, although it's not common.)
                                        We definitely don't want setting a base class property to invoke an arbitrary number of arbitrarily-ordered observers. Moreover, what if some of the subclasses actually override the setter entirely, instead of just adding an observer? That's clearly not implementable.
                                        Again, I'm not saying you/we can't pick a behavior and stick with it. I just want the tradeoffs to be clear.
                                        Jordan
                          
                                                          On Dec 10, 2015, at 7:23, Ling Wang < an00na@gmail.com> wrote:
                                                                                  When verifying my class object modal I actually found one issue of the current class property observers.
                                                    In the current implementation, when super class’s class property setter is called, subclasses’ observers don’t get called. But after the call of super setter, the value of this property accessed via subclasses(suppose them don’t overload get/set) does change. It means their properties are changed without their knowing it even though they explicitly define observers to observe the changes.
                                                                       ``` var backingVarForFooI = 0
                   
class Foo {
class var i: Int {
get {
return backingVarForFooI
}

    set \{                   
        backingVarForFooI = newValue                   
        print\(&quot;Foo\.i\.set \\\(newValue\)&quot;\)                   
    \}                   
\}                   

}
                   
class Bar: Foo {
override class var i: Int {
didSet {
print("Bar.i.didSet \(i)")
}
}
}
                   
print(Bar.i)
Foo.i = 3
print(Bar.i) ```
                                                    If we think about it, it doesn’t matter whether the proper is stored or calculated. Storage is just the implementation details, it doesn’t affect the interface or the concept. Besides, even calculated properties need storage if they are mutable.
                                                    After super class changes a property, people expect to get the changed value when they access the property via their subclasses(suppose they don’t overload get/set) and expect the corresponding observers to get called. So the class object modal that I speculated sharing properties among all subclasses and super class and notifying them about property changes is the only sound modal in this aspect. So the concern about overloading stored type properties with observers is not only about stored type properties but about all type properties.
                                                    So there is nothing special to separate stored type properties from calculated type properties. It supports my proposal to unite them under a more general keyword.
                                                    - Ling
                                                                                           On Dec 9, 2015, at 10:23 AM, Ling Wang < an00na@gmail.com> wrote:
                                                                                                      This is a legit concern that I didn’t consider before.
                                                                I think there are several options, from the most general to the most subtle: 1. Stored type properties are implicit `final`, so behave exactly the same as the current static stored properties. 2. Stored type vars are implicit `final`, as you suggested, so behave exactly the same as the current static stored vars. All other type properties(including stored type lets) are normally overridable. 3. Store type vars are overridable but can not be observed.
                                                                There could be a even more subtle option if my understanding of how classes exist in runtime is correct.
                                                                In my understanding, classes exist as singleton instances of their meta classes. If it is true, which I believe is the image in most people’s heads if they know about meta classes, then the class objects tree is exactly the same as the class hierarchy tree. Every subclass object contains(or points to) its super class object in its layout. The super class part is shared by all subclass objects and the super class object per se. So stored type properties are conceptually and naturally shared by the super class and all its subclasses, which behave exactly like the current static stored properties.
                                                                In this modal, the 4th option is: 4. Stored type vars are overridable and observable. When they are assigned new values, all their property observers defined in the class hierarchy are called, calling order is not significant, the reason of which will be addressed later.
                                                                Unfortunately, there is one last catch: if more than one classes assign a value to the property within their didSet observer, the final result is undefined.
                                                                This issue can not even be resolved by ordering observer calls from top to bottom in the class hierarchy because we can not meaningfully define the order within the same level if there are more than one subclasses in it.
                                                                So one addition to option 4: 4-1. Stored type vars’ didSet observers are not allowed to reassign value to the observed property.
                                                                But it is such a corner case that probably this limitation is acceptable.
                                                                What do you think? Is my understanding of class objects correct? Which option do you like best?
                                                                - Ling
                                                                                                               On Dec 8, 2015, at 5:40 PM, Jordan Rose < jordan_rose@apple.com> wrote:
                                                                                                
                                                                                                          On Dec 7, 2015, at 19:12, Ling Wang via swift-evolution < swift-evolution@swift.org> wrote:
                                                                                    Besides, we shouldn’t use `final` to denote storage at all for `final` is about inheritability/overridability not about storage.
                                                                                                       
                                                   Please remember that stored properties can be overridden in Swift:
                                                                                                       class Base { /*instance*/ var flag: Bool = true }
                                                                               class Sub : Base { override var flag: Bool { didSet { if flag { print("The flag was set!") } } } }
                                                   This is theoretically possible at the class level as well, but doesn't really make sense for what's currently spelled "static var", since you'd be accessing the same storage in different ways. Does the proposal mean that a stored "type var" is non-overrideable, but a computed "type var" is overrideable, implicitly?
                                                                            Jordan