Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specify explicitly getter & setter must be defined together #1972

Closed
scabug opened this issue May 11, 2009 · 5 comments
Closed

Specify explicitly getter & setter must be defined together #1972

scabug opened this issue May 11, 2009 · 5 comments
Assignees
Milestone

Comments

@scabug
Copy link

@scabug scabug commented May 11, 2009

If a property of an object is defined as read/write in the base class then += works for subclasses.

object Test {
  def main(args: Array[String]) {
    var m = new Mutable()
    m.a += 10
    m.b += 10 //WORKS
  }
}

abstract class Abstract {
  var a = 0
  def b = a
  def b_=(v: Int) = { this.a = v }
}

class Mutable extends Abstract

However if the property is defined as read only in the base class and extended to read/write in a subclass, then using += will yield "reassignment to val" compiler error.

object Test {
  def main(args: Array[String]) {
    var m = new Mutable()
    m.a += 10
    m.b += 10 //error: reassignment to val
  }
}

abstract class Abstract {
  var a = 0
  def b = a
}

class Mutable extends Abstract {
  def b_=(v: Int) = { this.a = v }
}

Same applies to *=, -=, and other variations.

This problem was replicated on 2.7.4 and 2.7.3 (other versions were not tested).

@scabug
Copy link
Author

@scabug scabug commented May 11, 2009

Imported From: https://issues.scala-lang.org/browse/SI-1972?orig=1
Reporter: @lexn82

Loading

@scabug
Copy link
Author

@scabug scabug commented May 15, 2009

@dubochet said:
The Scala specification says:

�6.12.4 (simplified)
l <ins>= r can be re-interpreted as l = l </ins> r only when both

  1. ldoes not define +=directly of through an implicit conversion
  2. l is a variable of a type containing +.

�4.2 (simplified)
An implementation of a class containing variable declarations may define these variables using variable definitions, or it may define setter and getter functions directly.

The specification is not completely clear, but can be read to say that both setter and getter must be defined in the same class, not inherited, to be equivalent to a variable and to allow using +=. As such, the behaviour you report follows the specification.

Clearly, this could be improved, but it requires a change of specification. I'll reassign the issue to the Scala community to be reconsidered when we have more time, or by an external contributor.

Loading

@scabug
Copy link
Author

@scabug scabug commented May 19, 2009

@lexn82 said:
Thank you for pointing out that both getter and setter must be defined in the same class for code to compile. Here is a workaround based on that.

object Main {
    def main(args: Array[String]) = {
        val m = new Mutable()
        m.a += 10
        m.b += 10 // WORKS
    }
}

abstract class Abstract {
    var a = 0;
    def b = a;
}

class Mutable extends Abstract {
    override def b = a // makes it work
    def b_=(v: Int) { this.a = v }
}

My take on the language specification �4.2.
(I am merely presenting my logic on the subject matter in a straight-forward fashion, please consider it as a constructive argument rather than criticism).

A variable declaration var x : T is equivalent to declarations of a getter function x
and a setter function x _=, defined as follows:
def x : T
def x _= ( y : T ): Unit

This simply states that variable declaration is equivalent to declaration of a getter and a setter. There are no restriction placed, specifically there is no "getter and setter must be in the same class" restriction.

An implementation of a class containing variable declarations may define these
variables using variable definitions, or it may define setter and getter functions di-
rectly.

This paragraph merely elaborates on the equivalence definition. It states how implementations MAY define a var. The verb MAY is non-restrictive and does not cover all the options, this verb merely hints on the possibilities (e.g.: I may go for a walk, or I may go see a movie. However I may just stay home and watch tv).
If the restriction "getter and setter must be in the same class" was intended, the specification would explicitly say: "An implementation of a class containing variable declarations may define these variables using variable definitions, or it MUST define setter and getter functions directly."

May and must are not interchangeable in general, however in your interpretation, you are clearly rewriting may into must: "The specification is not completely clear, but can be read to say that both setter and getter must be defined in the same class..."

By similar logic, the sentence

This long and boring proof may be right.

can be turned into

This long and boring proof must be right.

A change with very clear consequences.

Since may is non-restrictive, when another option appears, then the original definition must be used to handle such option. So we should consider

A variable declaration var x : T is equivalent to declarations of a getter function x
and a setter function x _=, defined as follows:
def x : T
def x _= ( y : T ): Unit

In the code to reproduce the problem both getter and setter are declared and defined. So misbehaviour of += must be a bug.

Granted, this can be a minor bug with a time-consuming fix. However an improvement would not require a change in specifications.

Loading

@scabug
Copy link
Author

@scabug scabug commented Oct 15, 2013

@gkossakowski said:
Unassigning and rescheduling to M7 as previous deadline was missed.

Loading

@scabug
Copy link
Author

@scabug scabug commented Mar 12, 2014

@adriaanm said:
Clarified in the upcoming markdown version of the spec.

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants