Get superclasses function in Scala - scala

What would be a short functional way to get the superclasses of a given Class instance in Scala?
All I could come up with is this
def supers(cl: Class[_]): List[Class[_]] = {
cl :: Option(cl.getSuperclass).map(supers).getOrElse(Nil)
}
Does anyone know a shorter form with some fancy functional constructs?

Not exactly fancy functional constructs, but (slightly) shorter:
def supers(cl: Class[_]): List[Class[_]] = {
if (cl == null) Nil else cl :: supers(cl.getSuperclass)
}
scala> class Foo; class Bar extends Foo; class Baz extends Bar
defined class Foo
defined class Bar
defined class Baz
scala> supers(classOf[Baz])
res9: List[Class[_]] = List(class Baz, class Bar, class Foo, class java.lang.Object)
Note that this gives you the class and all of it's superclasses, but then again so does the one provided by the OP.

Related

Built-in Support for String -> Trait?

Given the following:
scala> trait Foo
defined trait Foo
scala> case object Bip extends Foo
defined module Bip
scala> case object Bar extends Foo
defined module Bar
Is there any feature, built into Scala, that can make a Foo from a String?
example:
f("Bip") === Bip
f("Bar") === Bar
f("...") === Exception (or maybe returns None)?
You could use macros, but it may be easier to just use simple Java reflection:
namespace org.example
import scala.util.control.Exception._
object Demo extends App {
sealed trait Foo
case class Bar() extends Foo
case class Bip() extends Foo
def makeFoo(s: String): Option[Foo] = {
catching(classOf[Exception]).opt(Class.forName("org.example.Demo$" + s).newInstance.asInstanceOf[Foo])
}
println(makeFoo("Bar")) // Some(Bar())
println(makeFoo("Bip")) // Some(Bip())
println(makeFoo("Bop")) // None
}
If you put all the case classes in a single object container like I did above, the class names should be pretty predictable.
Edit: Added optional wrapper for exceptional cases.

Why do val and def implement abstract methods at different times?

I was working with scala and did something like this:
trait Foo { val a: String }
trait Foo2 extends Foo { val a = "foo" }
trait Bar extends Foo { val b = a + "-bar" }
object Bar2 extends Bar with Foo2
I expected that Bar2.b would be "foo-bar", but it ends up being "null-bar". Bar2.a is "foo" as expected.
If I change from val to def for definitions of 'a' like this:
trait Foo { def a: String }
trait Foo2 extends Foo { val a = "foo" }
trait Bar extends Foo { val b = a + "-bar" }
object Bar2 extends Bar with Foo2
Bar2.b is actually "foo-bar".
In example 2, the def 'a' from Foo2 that implements the abstract one in Foo is put into the definition of Bar2 before the val 'b' is evaluated. In example 1, the val 'a' from Foo2 overrides the val 'a' from Foo after val 'b' is defined in Bar/Bar2.
Why is this the case? Why do val and def implement abstract methods at different times?
You always want to use either def or lazy val in traits (rather than just val) to avoid the awkward behavior you discovered.
As for why, which gets to the low-level details of Scala's implementation in the JVM, check out Josh Suereth's excellent talk "Binary Resilience" from Scala Days 2012.
It's because there is Java behind. Initialized (non abstract) vals are translated to public getters with private fields and they are initialized in certain order. Abstract vals are just getters. Check Java documentation on this. You may also see early initializers feature of Scala to find a better solution:
In Scala, what is an "early initializer"?
And also order of mixing-in matters. This should give you the right result:
object Bar2 extends Foo2 with Bar

is there any way to use import someValue._ to implement overriding methods in scala?

Is there any way to do anything like this:
scala> trait Foo { def f:Int=0 }
defined trait Foo
scala> class FooImpl extends Foo { override val f = 1 }
defined class FooImpl
scala> class Bar(foo:Foo) extends Foo{ import foo._ }
defined class Bar
scala> (new Bar(new FooImpl)).f
res2: Int = 0
scala> trait Foo { def f:Int }
defined trait Foo
scala> class Bar(foo:Foo) extends Foo{ import foo._ }
<console>:8: error: class Bar needs to be abstract, since method f in trait Foo of type => Int is not defined
class Bar(foo:Foo) extends Foo{ import foo._ }
^
scala>
...in a way that would result in a subclass overriding a parent method via import? Basically I think it would be interesting to be able to use composition without all the typing. Just curious if anything like this is possible.
What you are really asking for is a way to delegate method implementations to a member.
That issue has already been addressed here: Proxies / delegates in Scala
Basically, there is a way to do it using macros. An implementation can be found here: https://github.com/adamw/scala-macro-aop
The above provides a #delegate macro annotation that can be applied to a data member to cause the compiler to generate code to delegate method calls to that member. Note that macro annotations are an experimental feature planned for Scala 2.11, but you can use them with Scala 2.10 using the Macro Paradise compiler plugin.
Self-typing can help here (depending on exactly how you will be working with these classes - this isn't composition of instances, more composition of types):
trait Foo { def f:Int }
trait FooImpl extends Foo { override val f = 1 } // Needs to be a trait to be mixed in.
class Bar {
this: Foo => // This requires that any Bar instance must mix in a Foo (must 'be' a Foo)
}
Then you can instantiate and use your Bar instance similar to the following:
scala> (new Bar with FooImpl).f
res1: Int = 1

scala - implementing trait method with parameter that is child of expected type

I'm very new to Scala so forgive me if this is a real easy question but I could not find anything to help me or I could not figure out the right search terms. How can I make this work?
scala> trait Foo
defined trait Foo
scala> class FooImpl extends Foo
defined class FooImpl
scala> trait Bar { def someMethod(foo: Foo) }
defined trait Bar
scala> class BarImpl extends Bar { def someMethod(foo: FooImpl) {} }
<console>:10: error: class BarImpl needs to be abstract, since method someMethod in trait Bar of type (foo: Foo)Unit is not defined
(Note that Foo does not match FooImpl)
class BarImpl extends Bar { def someMethod(foo: FooImpl) {} }
Why doesn't FooImpl match Foo since Foo is a trait? I'm guessing I need to alter the signature of someMethod in Bar to say that I'm expecting something that extends Foo or "with Foo" but I can't seem to find documentation for this.
The problem is that the Bar trait's someMethod declaration specifies that any kind of Foo can be passed as an argument. You can think of this as its "contract". The contract says that any implementation of Bar will have a method someMethod that will accept any kind of Foo.
Your BarImpl class is an implementation of Bar and has a someMethod implementation. Unfortunately, its implementation of someMethod only accepts FooImpl kinds of Foo objects: not any kind of Foo. Since it doesn't allow you to pass in Foo objects that aren't FooImpl objects, it violates the contract specified by the trait definition. Implementations can't be more restrictive than the contract specifies.
As an example:
class FooImplB extends Foo
val bar: Bar = new BarImpl
val foo: Foo = new FooImplB
bar.someMethod(foo)
Here we declare a Bar called bar and a Foo called foo. According to the definition of Foo I should be able to pass foo into bar.someMethod. Except that BarImpl.someMethod only accepts FooImpl kinds of Foos and not FooImplBs! So we have a problem.
dhg explained why this doesn't work and why you probably don't really want it.
But if you still want it, you can do it like this:
trait Foo
class FooImpl extends Foo
trait Bar[F <: Foo] { def someMethod(foo: F) }
class BarImpl extends Bar[FooImpl] {
def someMethod(foo: FooImpl) {}
}
Jens Schauder's answer works but forces you to define the type in the trait signature. Instead, you can do the same on the method level:
scala> trait Foo
defined trait Foo
scala> class FooImple extends Foo
defined class FooImple
scala> trait Bar { def methodA[T <: Foo](foo: T) }
defined trait Bar
scala> class BarImpl extends Bar { def methodA[FooImpl](foo: FooImpl){} }
defined class BarImpl

How to prevent stack overflow when using Scala's Predef.implicitly

Given this simple code snippet I am astounded to provoke a stack overflow this easy:
implicit def foobar: Unit = implicitly[Unit]
In my little more complex use case I have the following situtation:
abstract class Foo {
type Repr_Tpe
protected implicit def repr2Ordered: Repr_Tpe => Ordered[Repr_Tpe]
}
class Bar extends Foo {
type Repr_Tpe = Long
protected implicit def repr2Ordered = implicitly[Repr_Tpe => Ordered[Repr_Tpe]]
}
Defining method repr2Ordered in class Foo does not work because type Repr_Tpe is abstract. So I decided to copy & paste the declaration and make a definition out of it; apparently leading to the stack overflow from above. Only by removing the modifier implicit from the definition in class Bar solves this problem.
Isn't there an elegant solution circumventing this pitfall?
You've defined foobar to be the implicit value of type Unit. Then you've defined it as the implicit value of type Unit. Thinking of it this way:
implicit def foobar: Unit = implicitly[Unit]
// you've defined foobar as the implicit value for Unit.
// so implicitly[Unit] is the same as calling foobar
// which is the same as:
implicit def foobar: Unit = foobar
You should be no more surprised that this causes a stack overflow than you would be by this statement:
def tharSheBlows: Unit = tharSheBlows
For something with a bit more elegance, I would use a view bound to ensure that the type paramater is Ordered instead.
scala> abstract class Foo[Repr_Tpe <% Ordered[Repr_Tpe]] {}
defined class Foo
scala> class Bar extends Foo[Long] {}
defined class Bar
scala> case class Unordered(data: String)
defined class Unordered
scala> class Bam extends Foo[Unordered] {}
<console>:10: error: No implicit view available from Unordered => Ordered[Unordered].
class Bam extends Foo[Unordered] {}
^
scala> implicit def bringOrder(u: Unordered) = new Ordered[Unordered] { def compare(that: Unordered) = u.data.compareTo(that.data) }
bringOrder: (u: Unordered)java.lang.Object with Ordered[Unordered]
scala> class Bam extends Foo[Unordered] {}
defined class Bam