Jay Taylor's notes

back to listing index

Abstract static methods in Scala - Stack Overflow

[web search]
Original source (stackoverflow.com)
Tags: stackoverflow.com
Clipped on: 2012-08-09

I've read this relevant post, but there weren't many concrete answers (poor language design more or less): Why can't static methods be abstract in Java

I'm a bit of a newcomer to Scala, is this possible in it (maybe with traits or something)?

I tried having my base class extend a trait, but then child classes are required to implement the abstract static method as a member method, when I really want them to be required to be implemented in the companion object.

asked Mar 21 at 10:35
Image (Asset 1/4) alt=32116

58% accept rate
1 upvote
 flag
can you tell us a bit more about your specific scenario? Why do you need the method to be in the companion object? There may be a different way to do it in scala. – Paolo Falabella Mar 21 at 13:48
  upvote
 flag
Here's an example: My base abstract class has an abstract autocorrect method, this doesn't need to be bound to a specific instance. I'm considering implementing methods in the base abstract class that would use this autocorrect method. If the functionality doesn't need to be overridden in child classes, then my child classes will need to implement their own autocorrect method - hence abstract static methods. – jiaweihli Mar 21 at 22:55
  upvote
 flag
If all you're doing is calling a method which is not bound to a specific instance, then put the method in the companion object, and call it from your class and all the subclasses. That would be the normal way to do it in Scala. – Matthew Farwell Mar 21 at 23:13
  upvote
 flag
The autocorrect method is intended to be abstract in my base class. The problem is there is no way of enforcing my subclasses to implement the autocorrect method. – jiaweihli Mar 22 at 2:46
1 upvote
 flag
@JiaweiLi the fact is that (unlike static methods in java) methods in a scala object are still instance methods, so on the client's side there is no semantic difference in how you call them. When you write AnObject.AMethod in scala you are NOT calling AMethod on the type, it's just that AnObject gives you the only instance of the singleton AnObject class. Please see this code where I've tried to illustrate what I mean – Paolo Falabella Mar 22 at 10:12
add comment

3 Answers

There aren't static methods in Scala [*], so your question is moot.

However, you can get what you want by extending an object with a trait:

scala> trait A { def foo(): Int }
defined
trait A

scala
> object C extends A { def foo(): Int = 5 }
defined module C

scala
> C.foo
res0
: Int = 5

which probably does what you want. There isn't really any way to force something to be implemented in the companion object of a class. The companion object might not exist.

[*] Technically, there are, but this is more of an implementation detail than an overall philosophy. See Method in companion object compiled into static methods in scala?

answered Mar 21 at 10:47
Image (Asset 2/4) alt=18.4k52855
  upvote
 flag
Actually, methods of a comanion object can be looked at as static methods of the class. – Nicolas Mar 21 at 10:58
2 upvote
 flag
@Nicolas Yes, there is a static forwarder in the class, but as I said, this is more of an implementation detail to help interop with Java. The Scala language itself doesn't have a notion of static methods. It's more of a singleton. – Matthew Farwell Mar 21 at 11:52
  upvote
 flag
How is it possible that the companion object doesn't exist? Shouldn't this be figured out during compile-time? – jiaweihli Mar 21 at 22:58
  upvote
 flag
@JiaweiLi Scala won't create a companion object unless you specify one or are using a case class. If you specify class Foo {}, then an object Foo doesn't automatically get created. So you can't assume that object Foo will exist. – Matthew Farwell Mar 21 at 23:10
  upvote
 flag
Out of curiosity, isn't that a flaw in the language design? (not being able to force existence of a companion object and some specific methods) Was this a conscious decision? – jiaweihli Mar 22 at 2:49
add / show 1 more comment

There are two possible explanations of why abstract static methods are not possible in Scala, Java, C++ or C#.

First is technical: abstract/virtual methods require a reference to an object (called this) to choose an override that will run. You provide no such object when you call a static method.

Second is logical: abstract/virtual static methods don't make any sense. When you call a static method, you always know the type which contains that method. You write:

MyClass.DoSomething(args)

If you have MyDerivative that extends MyClass, you can just define another static method:

MyDerivative.DoSomethingDifferent(args)

There is just no point in static virtual methods, since they will work just as ordinary static methods.

answered Mar 21 at 10:54
Image (Asset 3/4) alt=53429
3 upvote
 flag
By "abtract static methods", people often mean methods that must be implemented statically by any concrete subclass. Although I agree that it's not well shaped, there are valid argument in their existence. See for example how scala collections try to enforce the creation of a companion object with "stndard methods". – Nicolas Mar 21 at 11:02
add comment

I'm not sure what you would like to do with an abstract static method in java, but the only potential use case I've seen described in the past (I wish I remembered by whom...) is calling a method directly on a generic type parameter.

i.e. if java allowed something like this...

// this is not valid java...
// let's pretend we can define a static method in an interface
interface
Foo {
    static
String Foo();
}

// a class that implements our interface
class FooImpl implements Foo {
    public static
String Foo() {return "foo";}  
}

...we could use it on a generic parameter, to call Foo() directly on the type

static <T extends Foo> String Test() {
       
return T.Foo(); // even if our hypothetical static interface
                       
// was a valid thing, this would probably still fail
                       
// due to type erasure      
}

This would make somewhat more sense in C# because:

  1. Reified generics mean the type does not get erased
  2. in C# operators are static methods and you can define your own operators

Basically this means in a "pretend C#" with static interfaces, you could use something corresponding to the above "pretend java" code to write a generic method that works on any type that defines a specific operator (e.g. everything that has a "+" operator).

Now, back to scala. How does scala address this scenario? In part it doesn't. Scala has no static methods: an object is a singleton (i.e. a class with only one instance) but still a class with normal, instance methods, i.e. on objects you're still calling methods on the only instance, not directly on the type (even operators are methods in scala).

So in scala we would write:

trait Foo { def Foo:String }
object FooImpl extends Foo { def Foo = "foo" }

def Test(f: Foo) = f.Foo

...and call our method with

scala> Test(FooImpl)
res0
: String = foo
// note that FooImpl is still an instance (the only one) of FooImpl and not
// the type itself

You can do some tricks with implicits to avoid passing the only instance as a parameter:

implicit def aFoo = FooImpl
def Test2(implicit f: Foo) = f.Foo

now this works:

scala> Test2
res1
: String = foo

With more advanced tricks with implicits, scala also defines Numeric, that allows you to use operators on any numeric value, even though they don't implements a common interface out of the box.

answered Mar 21 at 15:44
Image (Asset 4/4) alt=5,7101315
add comment

Your Answer

 
community wiki

Not the answer you're looking for? Browse other questions tagged or ask your own question.