I want to keep the codebase clean by always using override in front of an overriding method implementation, but it seems to optional in Scala. Is there a tool, plugin, or parameters to check the code style conforms to using override?
The scala compiler requires an override keyword for all members that actually override a concrete member in a base class. It is forbidden if no base class has that member.
So, short answer: Yes, there is a tool, and it's the Scala compiler.
Note that the override modifer is optional when implementing abstract methods. This is a good design decision, as it allows you to retroactively mix in traits. If you accidentally mix in a trait with a conflicting concrete definition, the compiler warns you by telling you that you have a missing override modifier.
Related
For methods it is clear to me that accidentally overriding a method could have bad consequences, so requiring developers to be explicit about it with the "override" keyword seems like a good idea.
However, as initialisers are invoked on a type (as it were) instead of on an object, I don't understand what overriding means in this context nor what kind of mistakes the requirement for the "override" keyword on initialisers is preventing.
I find the override modifier to provide only a convenience and safety function of expressing the intent of a developer to either override an existing member of a class (when the modifier is present) or to introduce a new one (when the modifier is missing) so the compiler can perform the corresponding compile-time checks and inform the developer if the expressed intent could not be implemented (because there is nothing to override or because there is a signature collision with a member defined in one of the base classes).
You can argue that there is a difference between overriding a virtual member or providing a distinct statically dispatched initializer replicating the signature of an initializer of the base class. Technically, yes; but not semantically. Semantically you may still want to replicate the signature of an initializer of the base class, and the compiler is ready to perform the corresponding compile-time signature checks.
The Swift Language Guide in the chapter "Initialization" under the title Initializer Inheritance and Overriding says:
When you write a subclass initializer that matches a superclass designated initializer, you are effectively providing an override of that designated initializer. Therefore, you must write the override modifier before the subclass’s initializer definition. ...
As with an overridden property, method or subscript, the presence of the override modifier prompts Swift to check that the superclass has a matching designated initializer to be overridden, and validates that the parameters for your overriding initializer have been specified as intended.
From this excerpt the role of the override modifier indeed appears to be small — to verify the intent of a developer to match a signature from the base class or not.
It's said in the documentation that
In native JS types, all concrete definitions must have = js.native as body. Any other body will be handled as if it were = js.native, and a warning will be emitted. (In Scala.js 1.0.0, this will become an error.)
And that's correct. However I found that I can omit body at all (thus making definition abstract) and there is no warning and generated js seems to be the same as with js.native body.
So my question is: what's the difference between abstract definitions and concrete definitions with js.native body?
The difference is that an abstract definition is abstract, and, well, a concrete definition (with = js.native) is concrete, from Scala's type system point of view.
But then what? From the use site of the class or trait, is doesn't make a difference. This is similar to normal Scala (or Java): when using a method, it doesn't matter whether it is abstract or not.
So the real difference is on the definition site. In theory, choosing abstract or concrete boils down to this criterium:
Does this method have an actual implementation in JavaScript code (not only a documented contract)? If yes, it should be concrete; if not, it should be abstract.
Practically and pragmatically, note that an abstract method can only appear in an abstract class or a trait, and must be implemented in a subclass/subtrait.
In terms of facade, in a native class, most methods should be concrete (if not all). That is because in JS, classes usually have concrete methods. In fact, abstract methods do not even exist in JS. The only reasonable case of defining an abstract method in a native class is if the "contract/documentation" of that class stipulates than a) it should be subclassed and b) subclasses should implement a particular method (not implemented in the superclass). This documented contract is as close as JS can get to abstract methods.
In JS traits, methods should usually be abstract (and the traits themselves be #ScalaJSDefined rather than #js.native). That is because traits/interfaces themselves do not even exist in JS. They only exist by their documented contract, which specifies what methods must/will be implemented by classes that satisfy this interface.
The only reasonable use case for concrete methods in (#js.native) JS traits is for DRYness. If several classes of a native API implement the same (large) set of methods, it can be reasonable to gather those methods in a native trait. In order not to have to repeat their definitions in all classes, they can be made concrete in the trait (if they were abstract, the classes would need to provided a concrete version to satisfy the contract). Note that such traits cannot be extended by non-native (#ScalaJSDefined) JS classes.
In the cases where you don't want to figure out the above "theoretical" criterium, use the following rule of thumb:
Is the method in a native JS class? If yes, it is almost certainly concrete.
Is it in a JS trait? If yes, it is almost certainly abstract (and the trait should be #ScalaJSDefined).
I have a method that takes type parameters with an implicit view bounds on them. Can I use the #implicitNotFound annotation to give nicer compiler errors when the method is called with invalid data types?
The documentation for the method is useless and even the source code doesn't help, and all the examples of use online are at the trait or class level.
No, you cannot directly do that. As you’ve noticed, #implicitNotFound annotates traits or classes. You could, however, make a special implicit type just for that method and annotate it if you really wanted to have a custom message.
Why is the "abstract" keyword for class definition optional in Scala, and how do I force the Scala compiler to tell me when my class is abstract?
Here an example that I wrote in Eclipse:
class Toto[T] {
def get(index: Int): T
}
object Toto {
def create[T]: Toto[T] = new Toto[T]
}
This seems to be a perfectly valid class definition in Scala, although it does NOT define the required get method, and is NOT prefixed with abstract. If you don't need the abstract keyword, then why does it exist? And if you want to be told that your class is actually abstract, how do you get the compiler to tell you?
This is not valid scala code, abstract is required, and instanciation forbidden. From the spec (5.2, p63):
The abstract modifier is used in class
definitions. It is redundant for
traits, and mandatory for all other
classes which have incomplete members.
Ab- stract classes cannot be
instantiated (§6.10) with a
constructor invocation unless
followed by mixins and/or a refinement
which override all incomplete members
of the class. Only abstract classes
and traits can have abstract term
members.
The code produces an error in the REPL : error: class Toto needs to be abstract, since method get is not defined
I get the proper behavior with the same message in Eclipse too. You should check whether you get the same error with and without eclipse. Whichever is true, I guess if you have exactly the code you posted without an error (does it run?), a bug repport will be warranted.
To answer my own question: In Eclipse, you can only tell if a class is correct if all other classes compile without errors! In other word, you can't trust anything Eclipse says about a class unless there are no errors in other classes.
So if you have errors in several classes, then there is no way of knowing which ones are the real errors, and neither if a class without errors is correct.
You just have to repeatedly loop on the errors, fixing any one that makes sense, and hoping the others errors that don't make sense are eventually going to just disappear.
Is it good practice to use the override keyword when implementing abstract methods defined in traits?
trait Tooth {
def ache(): Unit
}
class Molar extends Tooth {
override def ache(): Unit = {}
}
In the above example, I understand that the override keyword is optional; but is it advisable? On which side of the terseness vs. safety trade-off should I fall?
override does one thing for you there: when removing Tooth.ache but not its implementations later on, you will get compiler errors. In particular, this forces implementations of Tooth (written by yourself or others) to be "close" to Tooth in a certain sense, namely that deprecated methods vanish (or are at least reconsidered).
This may or may not be desired.
Personally, when I see
override def whatever()
the first thing I think is, "I wonder how this was supposed to behave before?"
Since this is an unhelpful thought if it was an abstract method, I find it both more terse and more safe to leave it off.
I usually don't use override when implementing an abstract method. It's not wrong, but redundant, and I prefer to keep my code as short as possible while maintaining clarity. But I realize it's not a clear-cut case.
I always use it, to indicate member that were declared on super classes, even if abstract.