Say I have a class:
class SomeClass[+A <: AnyRef, +B <: Any]
To specify it I always have to specify the types of generic parameters too. I.e. to specify its most general version as a method parameter type I have to do def someMethod(param1: SomeClass[AnyRef, Any])
or new SomeClass[AnyRef, Any]
to instantiate it. It becomes a major pain when it comes to more complex types which have complex generics.
Is there a way to make the [AnyRef, Any]
part implied when I don't provide generic information? For instance def someMethod(param1: SomeClass)
?
Is there a way the _
could help me solve this problem and how?
P.S. I apologize for originally not stating the question as clearly.
As suggested in my comment, doing something like this can save some typing and is pretty straightforward:
type SomeClassAny = SomeClass[AnyRef, Any]
If you don't truly care about what type this thing is going to have, you can parametrize it with [_, _]. Examples might be things like
val thing = new SomeClass[_, _]()
or
def thingDoer(sc: SomeClass[_, _]) { /* Stuff */ }
To be a bit more clear about its nature, the underscore is known as the "existential type", and it's basically the equivalent of a raw type in Java, and it can also function similar to wildcard type from Java. For example, this schizophrenic Java code
public void thingThatTakesAMapList(List<? extends Map> mapList) { /* Whatever */ }
is the same as this Scala code
def thingThatTakesAMapList(mapList: List[_ <: Map[_, _]]) { /* Some incredibly wild subroutine */ }
Also, it's worth noting the distinguishment between List[Any] and List[_] is... very subtle. It is to say that the former is a list of Any, and the latter is a list of [I don't know/care]. _ is quite different from Any, though. For example, if you had a class with this signature
class SillyClass[T <: Map[_, _]]
it would not be valid to do this
val thing = new SillyClass[Any]()
while it could be valid for you to do this
val thing = new SillyClass[HashMap[_, _]]()
and, if a function took a SillyClass as a parameter, you could write
def sillyClassTaker(sc: SillyClass[_])
and be certain that sc was not going be parametrized over type Any; it's parametrized over some unknown subclass of Map[_, _]. That is to say that the underscore is a placeholder, but it still requires that valid type parameters exist in its place. So, while that's all cool and all... I don't particularly recommend using it too much. If you need to do something... wildcard-y, or simply don't care about the type parameters, it's a good option to consider, though.
How about this?
scala> :paste
// Entering paste mode (ctrl-D to finish)
class SomeClass[+A <: AnyRef]
object SomeClass {
def apply() = new SomeClass[AnyRef]
}
// Exiting paste mode, now interpreting.
defined class SomeClass
defined module SomeClass
scala> SomeClass()
res47: SomeClass[AnyRef] = SomeClass@4f63b5
Edit:
I think you want something like default arguments, but at the type level. Unfortunately Scala does not have any such feature. You can use type aliases as suggested by @hyhnhjl. That to me seems your best bet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With