- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
open class in scala and polymorphism
Mon, 2009-03-30, 13:19
Hello,
I try to implement a visitor pattern using open-class principle like in ruby or like using the AspectJ introduction. I want to weave a set of "flatshort" methods into a hierarchy of Java classes (I can not modify their sourcce code).
My hierarchy contains an EPackage class which has a set of EClassifier that can be EClass or EDataType.
I use the implicit def mechanism to manage the openclass definition (see code below).
However, when I call value.getEClassifiers.toArray.foreach(e=>e.asInstanceOf[EClassifier].flatshort) (in the flatshort method in the EPackage context so value is an EPackage), the flatshort method of RichEClassifier is always invoked although the objects are EClass or EDataType. I expected that the invocation of the flatshort method of RichEClass or EDatatype. In fact, I lost the dynamic binding because, the Rich element object which is created is always a RichEClassifier.
Is there a way to manage easily this problem ?
It works if I replace implicit def e(xs:EClassifier ) = new RichEClassifier(xs)
with :
implicit def e(xs:EClassifier ) = {
var result : RichEClassifier =null;
if (xs.isInstanceOf[EClass]){
result = new RichEClass(xs.asInstanceOf[EClass])
}else if(xs.isInstanceOf[EClassifier]){
result =new RichEClassifier(xs.asInstanceOf[EClassifier])
}else if(xs.isInstanceOf[EDataType]){
result =new RichEDataType(xs.asInstanceOf[EDataType])
}
result
}
But is is a bit horrible. Is there any other solution.
Here is the example of code which does not work as expected.
class RichEPackage (value: org.eclipse.emf.ecore.EPackage) {
implicit def e(xs:EClassifier ) = new RichEClassifier(xs)
implicit def e( xs: EClass) = new RichEClass(xs)
implicit def e(xs: EDataType) = new RichEDataType(xs)
implicit def e(xs: EPackage) = new RichEPackage(xs)
def flatshort() : Void = {
println(value.getName )
value.getESubpackages.toArray.foreach(e=>e.asInstanceOf[EPackage].flatshort)
value.getEClassifiers.toArray.foreach(e=>e.asInstanceOf[EClassifier].flatshort)
return null;
}
}
class RichEClassifier(value: EClassifier) {
def flatshort() : Void = {
println("classifier = " + this.getClass() + value.getClass() + " " +value.getName)
return null;
}
}
class RichEDataType(value: EDataType) extends RichEClassifier(value: EDataType){
override def flatshort() : Void = {
println("datatype = " + this.getClass() + value.getClass() + " " +value.getName)
return null;
}
}
class RichEClass(value: EClass) extends RichEClassifier(value: EClassifier) {
override def flatshort() : Void = {
println("EClass = " + this.getClass() + value.getClass() + " " +value.getName)
super.flatshort
return null;
}
}
Best regards,
Olivier
I try to implement a visitor pattern using open-class principle like in ruby or like using the AspectJ introduction. I want to weave a set of "flatshort" methods into a hierarchy of Java classes (I can not modify their sourcce code).
My hierarchy contains an EPackage class which has a set of EClassifier that can be EClass or EDataType.
I use the implicit def mechanism to manage the openclass definition (see code below).
However, when I call value.getEClassifiers.toArray.foreach(e=>e.asInstanceOf[EClassifier].flatshort) (in the flatshort method in the EPackage context so value is an EPackage), the flatshort method of RichEClassifier is always invoked although the objects are EClass or EDataType. I expected that the invocation of the flatshort method of RichEClass or EDatatype. In fact, I lost the dynamic binding because, the Rich element object which is created is always a RichEClassifier.
Is there a way to manage easily this problem ?
It works if I replace implicit def e(xs:EClassifier ) = new RichEClassifier(xs)
with :
implicit def e(xs:EClassifier ) = {
var result : RichEClassifier =null;
if (xs.isInstanceOf[EClass]){
result = new RichEClass(xs.asInstanceOf[EClass])
}else if(xs.isInstanceOf[EClassifier]){
result =new RichEClassifier(xs.asInstanceOf[EClassifier])
}else if(xs.isInstanceOf[EDataType]){
result =new RichEDataType(xs.asInstanceOf[EDataType])
}
result
}
But is is a bit horrible. Is there any other solution.
Here is the example of code which does not work as expected.
class RichEPackage (value: org.eclipse.emf.ecore.EPackage) {
implicit def e(xs:EClassifier ) = new RichEClassifier(xs)
implicit def e( xs: EClass) = new RichEClass(xs)
implicit def e(xs: EDataType) = new RichEDataType(xs)
implicit def e(xs: EPackage) = new RichEPackage(xs)
def flatshort() : Void = {
println(value.getName )
value.getESubpackages.toArray.foreach(e=>e.asInstanceOf[EPackage].flatshort)
value.getEClassifiers.toArray.foreach(e=>e.asInstanceOf[EClassifier].flatshort)
return null;
}
}
class RichEClassifier(value: EClassifier) {
def flatshort() : Void = {
println("classifier = " + this.getClass() + value.getClass() + " " +value.getName)
return null;
}
}
class RichEDataType(value: EDataType) extends RichEClassifier(value: EDataType){
override def flatshort() : Void = {
println("datatype = " + this.getClass() + value.getClass() + " " +value.getName)
return null;
}
}
class RichEClass(value: EClass) extends RichEClassifier(value: EClassifier) {
override def flatshort() : Void = {
println("EClass = " + this.getClass() + value.getClass() + " " +value.getName)
super.flatshort
return null;
}
}
Best regards,
Olivier
Mon, 2009-03-30, 14:27
#2
Re: open class in scala and polymorphism
Vladimir Kirichenko a écrit :
> implicit def eclr(xs:EClassifier ) = new RichEClassifier(xs)
> implicit def ecls( xs: EClass) = new RichEClass(xs)
> implicit def etype(xs: EDataType) = new RichEDataType(xs)
> implicit def epack(xs: EPackage) = new RichEPackage(xs)
>
> ?
>
In fact, it does not work.
Here is the output for the corresponding call
// println("classifier = " + this.getClass()+ " " + value.getClass()
+ " " +value.getName)
classifier = class p1.RichEClassifier class
org.eclipse.emf.ecore.impl.EClassImpl EAttribute
classifier = class p1.RichEClassifier class
org.eclipse.emf.ecore.impl.EClassImpl EAnnotation
classifier = class p1.RichEClassifier class
org.eclipse.emf.ecore.impl.EClassImpl EClass
...
the object type is class but the rich object type is RichEClassifier.
So when scala finds a class it replaces it by a RichEClassifier.
implicit def eclr(xs:EClassifier ) = new RichEClassifier(xs) match.
I put the project here.
https://transfert.inria.fr/fichiers/1b32c8a40c63db18793f2d4cef9d554f/Tes...
Olivier
Mon, 2009-03-30, 14:47
#3
Re: open class in scala and polymorphism
implicit conversions are chosen statically at compile time based on static types. So they work quite differently from Ruby style dynamic metaprogramming. There is a clean way to get around it without all your instanceof checking
implicit def e(eclr:EClassifier ) = ecl match {
case ecls : Eclass => new RichEClass(ecls)
case edt : EDataType => new RichEDataType(edt)
case _ => new RichEClassifier(ecl)
}
This works best if the EClassifier hierarchy is sealed.
On Mon, Mar 30, 2009 at 5:19 AM, Olivier Barais <olivier.barais@gmail.com> wrote:
implicit def e(eclr:EClassifier ) = ecl match {
case ecls : Eclass => new RichEClass(ecls)
case edt : EDataType => new RichEDataType(edt)
case _ => new RichEClassifier(ecl)
}
This works best if the EClassifier hierarchy is sealed.
On Mon, Mar 30, 2009 at 5:19 AM, Olivier Barais <olivier.barais@gmail.com> wrote:
Hello,
I try to implement a visitor pattern using open-class principle like in ruby or like using the AspectJ introduction. I want to weave a set of "flatshort" methods into a hierarchy of Java classes (I can not modify their sourcce code).
Mon, 2009-03-30, 15:07
#4
Re: open class in scala and polymorphism
2009/3/30 Olivier Barais :
> Hello,
> It works if I replace implicit def e(xs:EClassifier ) = new
> RichEClassifier(xs)
> with :
> implicit def e(xs:EClassifier ) = {
> var result : RichEClassifier =null;
> if (xs.isInstanceOf[EClass]){
> result = new
> RichEClass(xs.asInstanceOf[EClass])
> }else if(xs.isInstanceOf[EClassifier]){
> result =new
> RichEClassifier(xs.asInstanceOf[EClassifier])
> }else if(xs.isInstanceOf[EDataType]){
> result =new
> RichEDataType(xs.asInstanceOf[EDataType])
> }
> result
> }
>
> But is is a bit horrible.
As a side note, independently of your question, this is a terrible way
to write this code.
def e(xs : EClassifier) = e match { // this probably shouldn't be
EClassifier as you'll stop midway through?
case (ys : EClass) => new RichEClass(ys);
case (ys : EClassifier) => new RichEClassifier(ys);
case (ys : EDataType) => new RichEDataType(ys);
}
Mon, 2009-03-30, 16:57
#5
Re: open class in scala and polymorphism
Thanks for these infos.
Do you have some articles that explain why there is no open class support in scala
Olivier
2009/3/30 James Iry <jamesiry@gmail.com>
Do you have some articles that explain why there is no open class support in scala
Olivier
2009/3/30 James Iry <jamesiry@gmail.com>
implicit conversions are chosen statically at compile time based on static types. So they work quite differently from Ruby style dynamic metaprogramming. There is a clean way to get around it without all your instanceof checking
implicit def e(eclr:EClassifier ) = ecl match {
case ecls : Eclass => new RichEClass(ecls)
case edt : EDataType => new RichEDataType(edt)
case _ => new RichEClassifier(ecl)
}
This works best if the EClassifier hierarchy is sealed.
On Mon, Mar 30, 2009 at 5:19 AM, Olivier Barais <olivier.barais@gmail.com> wrote:Hello,
I try to implement a visitor pattern using open-class principle like in ruby or like using the AspectJ introduction. I want to weave a set of "flatshort" methods into a hierarchy of Java classes (I can not modify their sourcce code).
Mon, 2009-03-30, 17:07
#6
Re: open class in scala and polymorphism
On Mon, Mar 30, 2009 at 8:47 AM, Olivier Barais <barais@irisa.fr> wrote:
Thanks for these infos.
Do you have some articles that explain why there is no open class support in scala
Scala sits on top of the Java Virtual Machine and as version 6 of the JVM, there is no open class support. So, from a purely technical perspective, there is a significant performance hit to emulate open classes.
At the philosophical level, Scala's focus on immutability is at odds with open classes. Java focuses on mutable data and gives second class support to immutability. Ruby focuses on mutable data *and* mutable programs with open classes. Having programmed in Java, Ruby and Scala, I find that immutable data and immutable code leads to the most stable, bug-free, predictable code.
It might be worthwhile to see what you can do with Scala and pattern matching as well as structural typing and see if you can code stuff up without Aspects or open classes.
Olivier
2009/3/30 James Iry <jamesiry@gmail.com>
implicit conversions are chosen statically at compile time based on static types. So they work quite differently from Ruby style dynamic metaprogramming. There is a clean way to get around it without all your instanceof checking
implicit def e(eclr:EClassifier ) = ecl match {
case ecls : Eclass => new RichEClass(ecls)
case edt : EDataType => new RichEDataType(edt)
case _ => new RichEClassifier(ecl)
}
This works best if the EClassifier hierarchy is sealed.
On Mon, Mar 30, 2009 at 5:19 AM, Olivier Barais <olivier.barais@gmail.com> wrote:Hello,
I try to implement a visitor pattern using open-class principle like in ruby or like using the AspectJ introduction. I want to weave a set of "flatshort" methods into a hierarchy of Java classes (I can not modify their sourcce code).
--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp
Mon, 2009-03-30, 17:17
#7
Re: open class in scala and polymorphism
Ok, thanks a lot, it is clear.
I will keep playing with scala and try to see what I can do with Scala and pattern matching
Olivier
David Pollak a écrit :
I will keep playing with scala and try to see what I can do with Scala and pattern matching
Olivier
David Pollak a écrit :
cdbebedf0903300857g76dd4238w72d984fc2aad6010 [at] mail [dot] gmail [dot] com" type="cite">
On Mon, Mar 30, 2009 at 8:47 AM, Olivier Barais <barais [at] irisa [dot] fr" rel="nofollow">barais@irisa.fr> wrote:
Thanks for these infos.
Do you have some articles that explain why there is no open class support in scala
Scala sits on top of the Java Virtual Machine and as version 6 of the JVM, there is no open class support. So, from a purely technical perspective, there is a significant performance hit to emulate open classes.
At the philosophical level, Scala's focus on immutability is at odds with open classes. Java focuses on mutable data and gives second class support to immutability. Ruby focuses on mutable data *and* mutable programs with open classes. Having programmed in Java, Ruby and Scala, I find that immutable data and immutable code leads to the most stable, bug-free, predictable code.
It might be worthwhile to see what you can do with Scala and pattern matching as well as structural typing and see if you can code stuff up without Aspects or open classes.
Olivier
2009/3/30 James Iry <jamesiry [at] gmail [dot] com" target="_blank" rel="nofollow">jamesiry@gmail.com>
implicit conversions are chosen statically at compile time based on static types. So they work quite differently from Ruby style dynamic metaprogramming. There is a clean way to get around it without all your instanceof checking
implicit def e(eclr:EClassifier ) = ecl match {
case ecls : Eclass => new RichEClass(ecls)
case edt : EDataType => new RichEDataType(edt)
case _ => new RichEClassifier(ecl)
}
This works best if the EClassifier hierarchy is sealed.
On Mon, Mar 30, 2009 at 5:19 AM, Olivier Barais <olivier [dot] barais [at] gmail [dot] com" target="_blank" rel="nofollow">olivier.barais@gmail.com> wrote:
Hello,
I try to implement a visitor pattern using open-class principle like in ruby or like using the AspectJ introduction. I want to weave a set of "flatshort" methods into a hierarchy of Java classes (I can not modify their sourcce code).
Mon, 2009-03-30, 17:27
#8
Re: open class in scala and polymorphism
David Pollak wrote:
> At the philosophical level, Scala's focus on immutability is at odds
> with open classes. Java focuses on mutable data and gives second class
> support to immutability. Ruby focuses on mutable data *and* mutable
> programs with open classes. Having programmed in Java, Ruby and Scala,
> I find that immutable data and immutable code leads to the most stable,
> bug-free, predictable code.
Actually a lot of implicit conversions is actually used for the same
purpose as open classes. I mean those ones with RichXX-peers. So it's
really sad that JVM have no such ability to implement open classes in scala.
Mon, 2009-03-30, 18:07
#9
Re: open class in scala and polymorphism
David Pollak wrote:
>
> On Mon, Mar 30, 2009 at 8:47 AM, Olivier Barais > wrote:
>
> Thanks for these infos.
>
> Do you have some articles that explain why there is no open class
> support in scala
>
>
> Scala sits on top of the Java Virtual Machine and as version 6 of the
> JVM, there is no open class support. So, from a purely technical
> perspective, there is a significant performance hit to emulate open classes.
>
>
I disbelieve.
What would be the performance hit of allowing open classes? As long as the open classes still had
to be defined at compile time, there'd be no run-time penalty at all -- in fact, the runtime
wouldn't know the class had been opened.
~~ Robert Fischer.
Grails Training http://GroovyMag.com/training
Smokejumper Consulting http://SmokejumperIT.com
Enfranchised Mind Blog http://EnfranchisedMind.com/blog
Check out my book, "Grails Persistence with GORM and GSQL"!
http://www.smokejumperit.com/redirect.html
Mon, 2009-03-30, 19:07
#10
Re: open class in scala and polymorphism
You're talking about two different things. Ruby style dynamic meta-programming on the one hand vs a static uber-mixin capability. I.e.
// in one file
class Foo {
def bar = ...
}
// in another file
class Foo {
def baz = ...
}
// synthesized by compiler, linker, or whatever
class Foo {
def bar = ...
def baz = ...
}
The barrier to this is practical (it plays hell with separate compilation) and conceptual (it plays hell with certain notions of encapsulation). But it's certainly not impossible and wouldn't have any performance impact.
On Mon, Mar 30, 2009 at 10:01 AM, Robert Fischer <robert.fischer@smokejumperit.com> wrote:
// in one file
class Foo {
def bar = ...
}
// in another file
class Foo {
def baz = ...
}
// synthesized by compiler, linker, or whatever
class Foo {
def bar = ...
def baz = ...
}
The barrier to this is practical (it plays hell with separate compilation) and conceptual (it plays hell with certain notions of encapsulation). But it's certainly not impossible and wouldn't have any performance impact.
On Mon, Mar 30, 2009 at 10:01 AM, Robert Fischer <robert.fischer@smokejumperit.com> wrote:
I disbelieve.
What would be the performance hit of allowing open classes? As long as the open classes still had to be defined at compile time, there'd be no run-time penalty at all -- in fact, the runtime wouldn't know the class had been opened.
~~ Robert Fischer.
Grails Training http://GroovyMag.com/training
Smokejumper Consulting http://SmokejumperIT.com
Enfranchised Mind Blog http://EnfranchisedMind.com/blog
Check out my book, "Grails Persistence with GORM and GSQL"!
http://www.smokejumperit.com/redirect.html
implicit def eclr(xs:EClassifier ) = new RichEClassifier(xs)
implicit def ecls( xs: EClass) = new RichEClass(xs)
implicit def etype(xs: EDataType) = new RichEDataType(xs)
implicit def epack(xs: EPackage) = new RichEPackage(xs)
?