Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 364669

Summary: [Xtend] Add sugar for immutable objects
Product: [Tools] Xtend Reporter: Steve Ash <stevemash>
Component: CoreAssignee: Project Inbox <xtend-inbox>
Status: CLOSED FIXED QA Contact:
Severity: enhancement    
Priority: P3 CC: bugs-eclipse.org, sven.efftinge
Version: 2.2.0Flags: sven.efftinge: juno+
Target Milestone: M7   
Hardware: PC   
OS: Windows 7   
Whiteboard:
Bug Depends on: 373184    
Bug Blocks:    

Description Steve Ash CLA 2011-11-24 00:19:36 EST
Build Identifier: 

A popular new language feature in a number of languages (Scala, Cylon) is a concise syntax for immutable object construction.  The use case is _not_ intended to support injection of collaborators-- that is still best served by DI.  This is intended to provide sugar for the common idiom of passing values into a constructor which need to be assigned to a final field (exposed through a property).  So all the time we see java like:

public class MyDataValue {
    private final String x;
    private final String y;
    public MyDataValue(String x, String y) {
        this.x = x;
        this.y = y;
    }
    public String getX() {
        return this.x;
    }
    public String getY() {
        return this.y;
    }
}

Here is the Scala equivalent of that class:

class MyDataValue(val x:String, val y:String)

You can also have mixed mutability and do:

class MyDataValue2(var x:String, val y:String)

so x will have get/set property access and y will only have get and will be final.

This is a common idiom with tremendous amount of noise reduction.  So it might fit well into Xtend.  If not, then fair enough.  Just thought I would log it for consideration since I didn't see it.

Reproducible: Always
Comment 1 Bardur Arantsson CLA 2011-12-10 03:59:22 EST
An addition that could be done to this to make it even more useful would be to generate

    withX(String x)
and withY(String y)

methods which return a "clone" of the instance with the X (resp. Y) property updated according to the argument given to the withX() method.

For example

  val a = new MyDataValue("0", "1")
  val ax = a.withX("00")
  val ay = a.withY("11")
  println(a)
  println(ax)
  println(ay)

would result in 

  MyDataValue{"0","1"}
  MyDataValue{"00","1"}
  MyDataValue{"0","11"}

(Obviously with a suitable toString() method... which could also be generated quite easily for these types of classes :)).
Comment 2 Sven Efftinge CLA 2012-03-08 03:12:11 EST
This would be an excellent use case for bug #373184
Comment 3 Sven Efftinge CLA 2012-04-20 05:56:00 EDT
just like @Property we decided to do this now based on an annotation and back-port it to a more generic annotation processing hook, when it's available.

Here's the proposal:

@Data class Person {
  String name
  String firstName
  val gender = Gender::MALE
}

1) all field are treated and marked as final. The internal field's name is renamed to _fieldName.
2) a constructor for the non-initialized fields is generated, the ordering of the parameters is the same as
 the declaration of the fields. Collections are copied to immutable variants in the constructor.
3) a getter method for each field is generated, if not existing.
4) equals and hash code are generated
5) toString() is generated returning a multiline string in the following form

DataClassName {
  field1 = toStringOfField1
  field2 = ...
}

Constraints:
1) A data class can only refer to immutable data types. That is other data classes and a predefined list of classes.
2) A data class can only extend other data classes.
3) A data class must have the @Data annotation.
4) A data class must have final fields only.
5) A data class must have one constructor.

Comments? Anything I missed?
Comment 4 Sven Efftinge CLA 2012-04-25 14:40:30 EDT
pushed to master
Comment 5 Eclipse Webmaster CLA 2017-10-31 10:49:02 EDT
Requested via bug 522520.

-M.
Comment 6 Eclipse Webmaster CLA 2017-10-31 11:00:06 EDT
Requested via bug 522520.

-M.