Uploaded image for project: 'Swift'
  1. Swift
  2. SR-4017

It's impossible to add a property setter through extension

    XMLWordPrintable

    Details

    • Type: Improvement
    • Status: Open
    • Priority: Medium
    • Resolution: Unresolved
    • Component/s: None

      Description

      It is currently not possible to add a setter to a computed property through an extension there that property also works properly outside the module (i.e. in other modules who import the extension).

      CGRect for example has two read-only computed properties height and width.

      Through an extension these properties can be shadowed by read-write computed properties like this:

      extension CGRect {
      
      	public var height: CGFloat {
      		get { return size.height }
      		mutating set { size.height = newValue }
      	}
      
      	public var width: CGFloat {
      		get { return size.width }
      		mutating set { size.width = newValue }
      	}
      }
      

      and then be used like this:

      var rect = CGRect()
      rect.height = 1
      rect.width = 2
      
      var height = rect.height
      var width = rect.width
      

      It works fine in the same module as where the extension was defined.

      It does not work however in other modules which import that extension. While the setters work fine, the getters will be considered "ambiguous" (between the original and the extension's implementations) and Swift provides no way to disambiguate this:

      import ModuleProvidingTheExtension
      
      var rect = CGRect()
      rect.height = 1 // works
      rect.width = 2 // works
      
      var height = rect.height // Ambiguous use of 'height'
      var width = rect.width // Ambiguous use of 'width'
      

      There is no workaround for this problem.

      Possible solutions:

      • Swift could provide a way to disambiguate the property access
        • at the call-site (would add weird syntax though)
        • at the import-site (e.g. import ModuleProvidingTheExtension.CGRect or ModuleProvidingTheExtension.CGRect.width - potentially very verbose)
        • by declaring that symbols in extensions always have precedence over symbols in the type being extended (won't work since CoreGraphic's CGRect.height/width is also added through extension)
        • by declaring symbol precedence depending on the order of module imports (potentially dangerous/unexpected?)
      • Swift could allow property getters to have a lower visibility than property setters which allowed for hiding the ambiguous getter (private get … in the extension)
      • Swift could allow adding a property setter through an extension without providing a getter

      The last solution (providing a setter without getter) would easily fix this issue. It maintains source-compatibility and introduces no new syntax.

      Example:

      extension CGRect {
      
      	public var height: CGFloat {
      		mutating set { size.height = newValue }
      	}
      
      	public var width: CGFloat {
      		mutating set { size.width = newValue }
      	}
      }
      

      It adds a setter to the existing read-only properties.
      Providing just a setter is only allowed if the property being affected is already defined somewhere - i.e. already has a getter.

      This could be extended to allowing subclasses to override only the setter of a property without having to override the getter just to call super's implementation. Same for protocol conformances where the getter would already be covered by a default implementation.

      I consider this to be more a bug than a feature request because overwriting the property in an extension leads to an unresolvable ambiguous access error in the getter only.

      If necessary I'll re-post this on the Swift Evolution Mailing List.

        Attachments

          Activity

            People

            Assignee:
            Unassigned Unassigned
            Reporter:
            marc Marc Knaup
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

              Dates

              Created:
              Updated: