Inner classes vs. immutability in Scala -


please @ following toy example:

case class person(name: string, address: person#address = null) {   case class address(street: string, city: string, state: string) {     def prettyformat = s"to $name of $city" // note use name here   }    def setaddress(street: string, city: string, state: string): person =     copy(address=address(street,city,state))    def setname(n: string): person = copy(name=n) } 

do see bug there? yes, following code print same message (john) in both cases:

val p1 = person("john").setaddress("main", "johntown", "ny") println(p1.address.prettyformat) // prints john of johntown val p2 = p1.setname("jane") println(p2.address.prettyformat) // prints john of johntown 

naturally because of $outer reference in address preserved in set methods, p2 inner object still refers john. issue fixed following or recreation of address object (wouldn't nice if had precooked copy-constructors in case classes?):

def setname(n: string) = copy(name=n).setaddress(address.street,address.city,address.state) 

however, problem becomes more annoying there several inner objects , tens of methods setname. conclusion immutability , class-inner classes mutually incompatible.

question: there design pattern or useful idiom structure of nested immutable objects in inner objects need access outer objects job.

so far have considered passing person implicit prettyformat or wrapping inner methods reader monad, current person applied monad returned prettyformat. other great ideas?

it not immutability , class-inner classes mutually incompatible, when create inner address class, bind person instance (else use static inner class, i.e., define address in companion object).

you problem more semantics of copy method provided case classes, not consider inner classes. either drop immutability or create real new person on modification:

def setname(n: string): person = person(n, street, city, state) 

do note should not pass direct address instance person(), definition each address type part of single person , makes sense person, can't exist outside of person, , can't pass outside new person being created. again, if not case, need rethink structure different semantics.

personally, thing following clearer/intuitive description of domain:

case class address(street: string, city: string, state: string) case class person(name: string, address: address) {    def prettyformat = s"to $name of ${address.city}" }  

and can create copies of addresses/people little worry , full immutability.


Comments

Popular posts from this blog

c# - Binding a comma separated list to a List<int> in asp.net web api -

Delphi 7 and decode UTF-8 base64 -

html - Is there any way to exclude a single element from the style? (Bootstrap) -