Static extension?

Is there a way to conceptually add a static method to a Java class using Scala 3 extensions? In other words, define an extension foo such that String.foo is valid?

Do you mean like so:

scala> object String
// defined object String
                                                                                
scala> extension (so: String.type) def foo = "valid"
def foo(so: String.type): String
                                                                                
scala> String.foo
val res0: String = valid

Does that compile? I am sure it used not to compile.
Or maybe it does for String but not in general? I recall a discussion about the compiler not generating those syntactic objects and self-types for Java classes.

I used the Scala 3.3.1 REPL for the code above.

I guess it works as there is no object called String already defined. If I skip the object declaration I get this error which is perfectly reasonable as there is no object String:

$ scala
Welcome to Scala 3.3.1 (17.0.8.1, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
                                                                                
scala> extension (so: String.type) def foo = "valid"
-- [E119] Type Error: ----------------------------------------------------------
1 |extension (so: String.type) def foo = "valid"
  |               ^^^^^^
  |               Java defined class String is not a value
1 error found
                                                                                
scala> 

I mean: we cannot expect to edit the compiled Java code. But we can add a scala singleton object called String…

Ah, I missed the object String thing. Well, the issue is that you now shadowed the original static methods on String, didn’t you?

Well, I could access it through java.lang.String and even re-expose it:

scala> object String:
     |   export java.lang.String.*
     | 
// defined object String

scala> String.CASE_INSENSITIVE_ORDER
val res0: java.util.Comparator[String] = java.lang.String$CaseInsensitiveComparator@222e5e72
             
1 Like

That’s what I was afraid of. I don’t want to define my own Scala objects because they won’t have the same full name. My case is not with String but with ArrayList. I’d like to be able to write this:

import java.util
// code that uses util.ArrayList 
util.ArrayList.foo

I’m trying to avoid code that mixes util.ArrayList and my.ArrayList (which is what I currently have).

But if String is your own object, you don’t even need an extension, do you? Why not define foo directly inside the object? The problem (I should have been more clear about my own case) is that I still cannot write java.lang.String.foo.

I guess you have to live with non-dot-notation on that one.

I would define foo as a normal top-level function with a good name and use that instead.

This is what I got:

$ scala                                                                                                           
Welcome to Scala 3.3.1 (17.0.7, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
                                                                                                                       
scala> extension (s: java.lang.String) def spam = ???
def spam(s: String): Nothing

That’ll let you write "foo".spam(...) but not String.spam(...).
(Also, the s that shadows the other s is confusing.)