views:

289

answers:

4

Well, I'm learning Scala so this question may be too basic for most people.

In Java I can have a static slot (function or variable) in a class, and then I will have that slot in inherited classes too.

In Scala I don't have static slots, but I have companion objects. But I'm finding out that those objects are not part of the inherited class, so if I have two classes Person and Student, and Person has a companion object with a variable all:List that returns a list of all persons so I can do Person.all, I was expecting that I could do Student.all too, but that's not the case.

Is there any way to get the same behaviour that I would get in java?

Thanks!

A: 

I think you have to stick with Scala's singleton (using object keyword)

object Hello {
  def say(s: String) = s + ", world!"
}

Then you use it as in Hello.say("Hello")

DroidIn.net
+1  A: 

Objects in Scala are not class-level entities like statics are in Java. They are simply a class definition and singleton instantiation rolled into one.

A companion object is a special case that allows the sharing of private data between it and its companion class.

Objects can extend classes, but not other objects. After all an 'object' is just a singleton instance - the class definition of an 'object' is hidden.

Is it reasonable to expect the special relationship between companion objects and companion classes to project an additional class hierarchy on companion objects?

I suspect the best way to achieve a dependency between Person and Student is to delegate.

object Person { val all = List(1,2,3) }
object Student { val all = Person.all.filter(_ % 2 == 0) }
Synesso
+4  A: 

I don't know if this is what you meant, but a companion object can extend from some traits/classes:

class Person
class Student extends Person

trait Aggregation[T] {
  val all: List[T]
}

object Person extends Aggregation[Person] {
  val all: List[Person] = List(new Person, new Person)
}

object Student extends Aggregation[Student] {
  val all: List[Student] = List(new Student, new Student)
}

println(Person.all) // prints all persons
println(Student.all) // prints all students
Walter Chang
+7  A: 

Theoretically speaking, Java's behavior in this respect is very broken. The fact that subclasses inherit static members really doesn't make any sense from an object-oriented point of view. Statics are really nothing more than fancy, scoped globals. Inheritance is something you see at the class level, but statics really aren't at the class level (since they're global) so inheritance shouldn't apply. The fact that it does in Java is...disturbing.

Scala has really taken the high road in this department; something for which we should all be grateful. As mentioned in another answer, the correct way to define "inherited" statics is to extract the inherited members out into a trait:

trait Inherited {
  def foo() { ... }
  def bar(i: Int) = ...
}

class Person {
  ...
}

object Person extends Inherited

class Student extends Person {
  ...
}

object Student extends Inherited

It may seem needlessly more verbose than Java, but trust me when I say that the semantics are a lot less surprising as a result.

Daniel Spiewak