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
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.)