# Why can't computed properties be overloaded (like methods can)?

**URL:** <https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881>\
**Category:** Using Swift\
**Created:** [March 27, 2020, 8:57pm UTC](https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881 "2020-03-27T20:57:20Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [March 27, 2020, 8:57pm UTC](https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881/1 "2020-03-27T20:57:20Z")

</div>

This compiles (Swift 5.2, Xcode 11.4):

```swift
struct S1 {
    static func foo() -> Int { 123 }
    static func foo() -> Bool { true }
    func foo() -> Int { 123 }
    func foo() -> Bool { true }
}
func foo() -> Int { 123 }
func foo() -> Bool { true }

```

But this doesn't:

```swift
struct S2 {
    static var foo: Int { 123 }
    static var foo: Bool { true } // ERROR: Invalid redeclaration of 'foo'
    var foo: Int { 123 }
    var foo: Bool { true } // ERROR: Invalid redeclaration of 'foo'
}

```

Why?

---

<div class="post-metadata">

**Author:** ![anon9791410](https://avatars.discourse-cdn.com/v4/letter/a/9fc348/32.png) [@anon9791410](https://forums.swift.org/u/anon9791410)\
**Post date:** [March 27, 2020, 9:49pm UTC](https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881/2 "2020-03-27T21:49:39Z")

</div>

It seems like that problem is a subset of the larger problem: you can't have multiple of anything that's parameterless, unless one is static and one is instance.

```swift
struct S<Whatever> {
  // You get only one of these…
  static func foo() { }
  static var foo: Whatever { fatalError() }

  // …and only one of these!
  func foo() { }
  var foo: Whatever { fatalError() }
}

```

---

<div class="post-metadata">

**Author:** ![typesanitizer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/typesanitizer/32/8661_2.png) [@typesanitizer](https://forums.swift.org/u/typesanitizer)\
**Post date:** [March 28, 2020, 12:43am UTC](https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881/3 "2020-03-28T00:43:02Z")

</div>

I don't know for a fact, but I suspect that there was no concrete use case for it. Even with method overloading, the fact that you can overload method types based purely on return types (as opposed to parameter types) is a bit spooky, because it leads to code where types can change easily without one noticing. I know some people consider allowing overloading based purely on return types a design oversight/mistake.

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [March 28, 2020, 6:15am UTC](https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881/4 "2020-03-28T06:15:50Z")

</div>

> [@anon9791410](#):
>
> you can't have multiple of anything that's parameterless, unless one is static and one is instance.

That's not exactly true. As shown in the OP, the following _multiple parameterless things_ (with or without static) compiles:

```swift
struct S {
    static func foo() { } 
    static func foo() -> Int { 123 } // Compiles.
    static func foo() -> Bool { true } // Compiles.
    static func foo() -> Float { 1.23 } // Compiles.
}

```

Changing those to computed properties does not compile (as shown in the OP), but there actually are scenarios where computed properties can be overloaded too:

```swift
struct S<A> {
    static var foo: Int { 123 }
    // static var foo: Bool { true } // Does not compile (as expected).
}
extension S where A == UInt16 {
    static var foo: Bool { true } // Compiles, but should it?
}
extension S where A == UInt32 {
    static var foo: String { "abc" } // Compiles, but should it?
}
extension S where A: UnsignedInteger {
    static var foo: Double { 1.23 } // Compiles, but should it?
}
extension S where A: FixedWidthInteger {
    static var foo: Double { 3.21 } // Compiles, but should it?
}

func bar1<T: UnsignedInteger>(_: T.Type) -> Double { return S<T>.foo }
func bar2<T: FixedWidthInteger>(_: T.Type) -> Double { return S<T>.foo }

func test() {
    print(S<UInt16>.foo as Int) // 123
    print(S<UInt16>.foo as Bool) // true
    print(S<UInt32>.foo as String) // abc
    print(bar1(UInt16.self)) // 1.23
    print(bar2(UInt16.self)) // 3.21
}
test()

```

---

<div class="post-metadata">

**Author:** ![anthonylatsis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anthonylatsis/32/39232_2.png) [@anthonylatsis](https://forums.swift.org/u/anthonylatsis)\
**Post date:** [March 28, 2020, 6:18am UTC](https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881/5 "2020-03-28T06:18:36Z")

</div>

Conditional and regular overloads share the same ambiguities and are effectively two sides of the same coin. With the introduction of conditional extensions, though, overloads that differ only in their generic signatures started to make a lot more sense, and at the current stage of language evolution, allowing the latter and banning Jens' example would only make the language less consistent and the compiler less uniform – actually, it had already become less consistent, since properties do support conditional overloads just like methods, and yet at some point we seem to had decided to ban the example at hand.

Edit: @Varun\_Gandhi Sorry, this was not meant to be a reply to your post specifically.

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [March 28, 2020, 7:09am UTC](https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881/6 "2020-03-28T07:09:29Z")

</div>

@Jessy, I think I get what you mean by this now:

> [@Jessy](#):
>
> you can't have multiple of anything that's parameterless

If by _parameterless_ you mean essentially _properties_ (computed or stored).

Because while this compiles:

```swift
func foo() -> Int { 123 }
func foo() -> Bool { true }

```

This doesn't:

```swift
func foo() -> Int { 123 }
func foo() -> Bool { true }
let foo = "abc" // ERROR: Invalid redeclaration of 'foo'

```

and more generally, no property (computed or stored) can be overloaded, eg:

```swift
var foo: Int { 123 }
var foo: Bool { true } // ERROR: Invalid redeclaration of 'foo'

```

```swift
let foo = { (string: String) -> String in string }
let foo = { (_ a: Int, _ b: Int) -> Int in a + b } // ERROR: Invalid redeclaration of 'foo'

```

with the notable exception of computed properties defined in conditional extensions that I mentioned [above](https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881/4).

---

<div class="post-metadata">

**Author:** ![anon9791410](https://avatars.discourse-cdn.com/v4/letter/a/9fc348/32.png) [@anon9791410](https://forums.swift.org/u/anon9791410)\
**Post date:** [March 28, 2020, 10:35pm UTC](https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881/7 "2020-03-28T22:35:13Z")

</div>

Sorry, I did not word things well. What I meant by "anything" is a _ **set** _ of member types.

> [@Jessy](#):
>
> you can't have multiple of anything that's parameterless, unless one is static and one is instance.

```swift
struct TypeDefinition {
  enum Ownership: CaseIterable {
    case `static`
    case instance
  }

  enum Member: Hashable {
    case `func`(Ownership)
    case `var`(Ownership)

    var ownership: Ownership {
      switch self {
      case .func(let ownership):
        return ownership
      case .var(let ownership):
        return ownership
      }
    }
  }

  init(parameterlessMembersWithTheSameName: Set<Member>) throws {
    guard (
      Ownership.allCases.allSatisfy { ownership in
        parameterlessMembersWithTheSameName
          .filter { $0.ownership == ownership }
          .count
          <= 1
      }
    ) else {
      struct TooManyError: Error { }
      throw TooManyError()
    }

    self.parameterlessMembersWithTheSameName = parameterlessMembersWithTheSameName
  }

  let parameterlessMembersWithTheSameName: Set<Member>

  var hasMultipleOfAnythingThatIsParameterless: Bool {
    parameterlessMembersWithTheSameName.count > 1
  }
}

```

As for the other overloads you mentioned, I like having support for them. It's this form I'm not so sure about…

```swift
struct S<A> {
  static var foo: Int { 123 }
}

extension S where A: FixedWidthInteger {
  static var foo: Int { 321 }
}

func bar<T: FixedWidthInteger>(_: T.Type) -> Int {
  S<T>.foo // 321.
  // Can we get access to 123 somehow?
}

```

---

<div class="post-metadata">

**Author:** ![Alejandro](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alejandro/32/46197_2.png) [@Alejandro](https://forums.swift.org/u/Alejandro)\
**Post date:** [March 29, 2020, 1:13am UTC](https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881/8 "2020-03-29T01:13:54Z")

</div>

> [@anon9791410](#):
>
> As for the other overloads you mentioned, I like having support for them. It's this form I'm not so sure about…
> 
> ```swift
> struct S<A> {
> static var foo: Int { 123 }
> }
> 
> extension S where A: FixedWidthInteger {
> static var foo: Int { 321 }
> }
> 
> func bar<T: FixedWidthInteger>(_: T.Type) -> Int {
> S<T>.foo // 321.
> // Can we get access to 123 somehow?
> }
> 
> ```

```swift
S<Any>.foo // 123

```

---

<div class="post-metadata">

**Author:** ![anon9791410](https://avatars.discourse-cdn.com/v4/letter/a/9fc348/32.png) [@anon9791410](https://forums.swift.org/u/anon9791410)\
**Post date:** [March 29, 2020, 2:16am UTC](https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881/9 "2020-03-29T02:16:46Z")

</div>

Good job. I was in the middle of [a puzzle-art-scavenger hunt](https://www.ravenchase.com/publicgames/rva-art-quest-no-host-required-play-anytime). Please disregard. 🙃

What about this one though?

```swift
struct S<A> {
  var foo = 123
}

extension S where A: FixedWidthInteger {
  var foo: Int { 321 }
}

var voidS = S<()>()
voidS.foo = 0
voidS.foo // 0

var intS = S<Int>()
intS.foo = 0
intS.foo // 321. How can we get the zero?

```

---

<div class="post-metadata">

**Author:** ![Alejandro](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alejandro/32/46197_2.png) [@Alejandro](https://forums.swift.org/u/Alejandro)\
**Post date:** [March 29, 2020, 2:40am UTC](https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881/10 "2020-03-29T02:40:42Z")

</div>

I don't know off the top of my head if there is a better solution, but you can use `Mirror`

```swift
struct S<A> {
  var foo = 123
}

extension S where A: FixedWidthInteger {
  var foo: Int { 321 }
}

var intS = S<Int>()
intS.foo = 0

Mirror(reflecting: intS).descendant("foo")! // 0

```

(Aside: I agree that there should be a better way to reference this than having to go through reflection.)

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [March 29, 2020, 7:56am UTC](https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881/11 "2020-03-29T07:56:18Z")

</div>

Another answer:

```swift
struct S<A> {
    var foo = 123
}

extension S where A: FixedWidthInteger {
    var foo: Int { 321 }
}

var intS = S<Int>()
intS.foo = 0
print(intS.foo) // 321. How can we get the zero?

func f<T: Any>(_ s: S<T>) -> Int { s.foo } // <-- Like this.
print(f(intS)) // 0

```

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [March 29, 2020, 8:04am UTC](https://forums.swift.org/t/why-cant-computed-properties-be-overloaded-like-methods-can/34881/12 "2020-03-29T08:04:22Z")

</div>

Assuming this behaves as intended, ie it is not caused by an accepts-invalid bug:

```swift
struct S<A> {
  var foo = 123
}

extension S where A: FixedWidthInteger {
  var foo: Int { 321 } // Compiles, but should perhaps be
                       // an invalid redeclaration?
}

```

Then why shouldn't this compile:

```swift
struct S<A> {
    var foo = 123
}

extension S where A: FixedWidthInteger {
    func foo() -> Int { 321 } // ERROR: Invalid redeclaration of 'foo()'
}

```

?

If there's no reason why that shouldn't compile, then why shouldn't this compile:

```swift
struct S {
    var foo = 123
    func foo() -> Int { 321 } // ERROR: Invalid redeclaration of 'foo()'
}

```

?

cc @Douglas_Gregor
