What does override do here? - scala

What does the override do here? After deleting override, I can still compile the program.
abstract class Animal {
def name: String
}
class Cat extends Pet {
override def name: String = "Cat"
}
Adapted from Tour of Scala: Upper Type Bounds:
https://docs.scala-lang.org/tour/upper-type-bounds.html

You are right, this is a particular case where removing it does not affect the program. Why override is allowed here is for various flexibility reasons:
say you want to add an implementation in the parent class Animal - that would work without affecting the behavior of Cat because you used the prophylactic
override in Cat to prevent that idea from affecting your extended class. So the subclass becomes just a little bit less tightly-coupled from your base class in this case.
say someone else deletes the abstract method name or renames it in the parent class (without knowing that method is being overridden). This would raise compile errors in all classes that overridden it, to he/she will know that this change should be thoroughly thought before being done, as it will affect the interface and the way clients interact with your code.
also it makes the compiler help you catch typos in subclasses: say you created another subclass and add a different method but misspell name for something else, say nme - you'll see that if you used override the compiler will warn you that nme does not override anything in the base class. (Thanks compiler!)
for me personally, using override in subclasses acts as a marker so I know that this method is also defined in the base class, without having to manually check the base class, which usually resides in a different file.
So it's more of a "best practice" thing rather than a necessity in this case, and everyone is free to use it as they see fit.

Related

Why the first base class in parent list must be non-trait class?

In the Scala spec, it's said that in a class template sc extends mt1, mt2, ..., mtn
Each trait reference mti must denote a trait. By contrast, the
superclass constructor sc normally refers to a class which is not a
trait. It is possible to write a list of parents that starts with a
trait reference, e.g. mt1 with …… with mtn. In that case the
list of parents is implicitly extended to include the supertype of
mt1 as first parent type. The new supertype must have at least one
constructor that does not take parameters. In the following, we will
always assume that this implicit extension has been performed, so that
the first parent class of a template is a regular superclass
constructor, not a trait reference.
If I understand it correctly, I think it means:
trait Base1 {}
trait Base2 {}
class Sub extends Base1 with Base2 {}
Will be implicitly extended to:
trait Base1 {}
trait Base2 {}
class Sub extends Object with Base1 with Base2 {}
My questions are:
Is my understanding correct?
Does this requirement (the first subclass in the parent list must be non-trait class) and the implicit extension only applies to class template (e.g. class Sub extends Mt1, Mt2) or also trait template (e.g. trait Sub extends Mt1, Mt2)?
Why this requirement and the implicit extension is necessary?
Disclaimer: I'm not and never was a member of the "Scala design committee" or anything like that, so the answer on the "why?" question is mostly speculation but I think a useful one.
Disclaimer #2: I've written this post over several hours and in several takes so it is probably not very consistent
Disclaimer #3 (a shameful self-promotion for the future readers): If you find this quite long answer useful, you might also take a look at my another long answer to another question by Lifu Huang on a similar topic.
Short answers
This is one of those complicated things for which I don't think there is a good short answer unless you already know what the answer is. Although my real answer will be long, here are my best short answers:
Why the first base class in parent list must be non-trait class?
Because there has to be only one non-trait base class and it makes thing easier if it is always the first
Is my understanding correct?
Yes, your implicit example is what will happen. However I'm not sure that it shows full understanding of the topic.
Does this requirement (the first subclass in the parent list must be non-trait class) and the implicit extension only applies to class template (e.g. class Sub extends Mt1, Mt2) or also trait template (e.g. trait Sub extends Mt1, Mt2)?
No, implicit extensions happens for traits as well. Actually how else you could expect Mt1 to have its own "supertype" to be promoted down to the class that extends it?
Actually here are two IMHO non-obvious examples proving this is true:
Example #1
trait TAny extends Any
trait TNo
// works
class CGood(val value: Int) extends AnyVal with TAny
// fails
// illegal inheritance; superclass AnyVal is not a subclass of the superclass Object
class CBad(val value: Int) extends AnyVal with TNo
This example fails because the spec says
The extends clause extends scsc with mt1mt1 with …… with mtnmtn can be omitted, in which case extends scala.AnyRef is assumed.
so TNo actually extends AnyRef which is incompatible with AnyVal.
Example #2
class CFirst
class CSecond extends CFirst
// did you know that traits can extend classes as well?
trait TFirst extends CFirst
trait TSecond extends CSecond
// works
class ChildGood extends TSecond with TFirst
// fails
// illegal inheritance; superclass CFirst is not a subclass of the superclass CSecond of the mixin trait TSecond
class ChildBad extends TFirst with TSecond
Again ChildBad fails because TSecond requires CSecond but TFirst only provides CFirst as the base class.
Why this requirement and the implicit extension is necessary?
There are three major reasons:
Compatibility with the main target platform (JVM)
Traits have "mixin" semantics: you have a class and you mix additional behavior in
Completeness, consistency and simplicity of the rest of the spec (e.g. of linearization rules). This might be restated as following: each class must declare 0 or 1 base non-trait classes and after compilation the target platform enforces that there will be exactly 1 non-trait base class. So it makes the rest of the spec easier if you just assume there is always exactly one base class. In such way you have to write this implicit extension rules only once rather than each time when the behavior depends on the base class.
Scala spec goals/intentions
I believe that when one reads a spec there are two different sets of questions:
What exactly is written? What is the meaning of the spec?
Why it is written so? What was the intention?
Actually I think in many cases #2 is more important than #1 but unfortunately specs rarely explicitly contain insights into that area. Anyway I will start with my speculations over #2: what were the intentions/goals/limitations of the classes system in Scala? The main high-level goal was to create a type system richer than the one in Java or .Net (which are quite similar) but that can be:
compiled back to an efficient code in those target platforms
allow reasonable two-way interaction between the Scala code and the "native" code in the target platforms
Side note: Support of the .Net was dropped years ago but it was one of the target platforms for years and this affected the design.
Single base class
Short summary: this section describes some reasons why Scala designers had a strong motivation to have the "exactly one base class" rule in the language.
A major problem with OO design and particularly inheritance is that AFAIK the question: "where exactly is the border between the "good and useful" practices and the "bad" ones?" is open. It means that each language must find out its own trade off between making impossible what is wrong and making possible (and easy) what is useful. Many believe that in C++, which obviously was a major inspiration for Java and .Net, that trade off is shifted too much into "allow everything even if it is potentially harmful" zone. It made many designers of newer languages to seek for more restricting trade off. Particularly both JVM and .Net platform enforce the rule that all types are split into "value types" (aka primitive types), "classes" and "interfaces" and each class, except the root class (java.lang.Object/System.Object), has exactly one "base class" and zero or more "base interfaces". This decision was a reaction to many issues of multiple inheritance including infamous "diamond problem" but actually many others as well.
Sidenote (about memory layout): Another major problem with multiple inheritance is objects layout in memory. Consider following ridiculous (and impossible in current Scala) example inspired by Achilles and the tortoise:
trait Achilles {
def getAchillesPos: Int
def stepAchilles(): Unit
}
class AchillesImpl(var achillesPos: Int) extends Achilles {
def getAchillesPos: Int = achillesPos
def stepAchilles(): Unit = {
achillesPos += 2
}
}
class TortoiseImpl(var tortoisePos: Int) {
def getTortoisePos: Int = tortoisePos
def stepTortoise(): Unit = {
tortoisePos += 1
}
}
class AchillesAndTortoise(handicap: Int) extends AchillesImpl(0) with TortoiseImpl(handicap) {
def catchTortoise(): Int = {
var time = 0
while (getAchillesPos < getTortoisePos) {
time += 1
stepAchilles()
stepTortoise()
}
time
}
}
The tricky part here is how to actually lay achillesPos and tortoisePos fields out in the memory (of the object). The issue is that you probably want to have only one compiled copy of all the methods in the memory and you want the code to be efficient. This means that getAchillesPos and stepAchilles should have know some fixed offset of the achillesPos regarding to the this pointer. Similarly getTortoisePos and stepTortoise should have know some fixed offset of the tortoisePos regarding to the this pointer. And all choices you have to achieve this goal don't look nice. For example:
You might decide that achillesPos is always first and tortoisePos is always second. But this means that in the instances of TortoiseImpl tortoisePos should also be the second field but there is nothing to fill the first field with so you waste some memory. Moreover if both AchillesImpl and TortoiseImpl come from pre-compiled libraries, you should have some way to move access to the fields in them as well.
You might try to "fix" this pointer on-the-fly when you call into TortoiseImpl (AFAIK this is the way C++ really works). This becomes especially funny when TortoiseImpl is an abstract class that is aware of the trait Achilles (but not the specific class AchillesImpl) via extends and tries to call back some methods from there via this or pass this to some method that takes Achilles as an argument so this has to be "fixed back". Note that this is not the same as the "diamond problem" because there is only one copy of all fields and implementations.
You might agree to have a unique copy of the methods compiled for each specific class that are aware of the specific layout. This is bad for memory usage and performance because it blows CPU caches and forces JIT to make independent optimizations for each.
You might say that no method except for getter and setter can have direct access to the fields and should use getters and setters instead. Or store all the fields in some kind of a dictionary which is effectively the same. This might be bad for performance (but this is the closest to what Scala does with mixin-traits).
In the actual Scala this issue does not exist because trait can't really declare any fields. When you declare val or var in a trait, you actually declare a getter (and a setter) method(s) that will be implemented by particular class that extends the trait and each class has full control over layout of the fields. And actually in terms of performance this most probably would work OK because JVM (JIT) can inline such a virtual call in many real-world scenarios.
End of the Sidenote
Another major point is interoperability with the target platform. Even if Scala somehow supported true multiple-inheritance so you can have a type that inherits from String with Date and that can be passed to both methods that expect String and that expect Date, how this would look like from the Java point of view? Also if the target platform enforces the rule that every class has to be an (indirect) sub-type of the same root class (Object), you can't work this around in your higher level language.
Traits and Mix-ins
Many think that "one class and many interfaces" trade-off that was made in Java and .Net is too restrictive. For example it makes it hard to share common default implementation of some of the interface methods between different classes. Actually over the time Java and .Net designers seem to come to the same conclusion and rolled out they own fixes for this kind of issues: Extension methods in .Net and then Default methods in Java. Scala designers added a feature called Mixins that was known to fare well in many practical cases. However unlike many other dynamic languages that has similar feature, Scala still had to meet the "exactly one base class" rule and other limitations of the target platform.
It is important to note that there are important scenarios when mixins are used in practice is to implement a variation of the Decorator or Adapter patterns both of which relies on the fact that you can restrict your base type to something more specific than Any or AnyRef. Prime example of such usage is the scala.collection package.
Scala syntax
So now you have following goals/restrictions:
Exactly one base class for each class
Ability to add logic to classes from mixins
Support of mixins with restricted base type
Classes from the target platform (Java) when seen from Scala are mapped to the Scala classes (because what else they can be mapped to?) and they come pre-compiled and we don't want to mess with their implementation
Other good qualities such as simplicity, type safety, determinism, etc.
If you want some kind of multiple inheritance support in your language, you need to develop conflict resolution rules: what happens when several base types provide some logic that would fit the same "slot" in your class. After prohibition of fields in traits we are left with the following "slots":
Base class in terms of the target platform
Constructors
Methods with the same name and signature
And possible conflict resolution strategies are:
Prohibit (fail compilation)
Decide which one wins and wipes others
Somehow chain them
Somehow preserve all with renaming. This is not really possible in JVM. For example in .Net see Explicit Interface Implementation
In a sense Scala uses all available (i.e. first 3) strategies but the high-level goal is: let's try to preserve as many logic as we can.
The most important part for this discussion is conflicts resolution for constructors and methods.
We want the rules to be the same for different slots because otherwise it is not clear how to achieve safety (if traits A and B both override methods foo and bar but resolution rules for foo and bar are different, invariants for A and B might easily be broken). Scala's approach is based on the class linearization. In short these is the way to "flatten" hierarchy of the base classes into a simple linear structure in some predictive way that is based on the idea that the lefter type in the with chain - the more "base" (higher in the inheritance) it is. After you do this, conflict resolution rule for methods becomes simple: you go through the list of the base types and chain behavior via super calls; if super is not called, you stop chaining. This produce quite predictable semantics that people can reason about.
Now assume you allow non-trait class to be not first. Consider following example:
class CBase {
def getValue = 2
}
trait TFirst extends CBase {
override def getValue = super.getValue + 1
}
trait TSecond extends CFirst {
override def getValue = super.getValue * 2
}
class CThird extends CBase with TSecond {
override def getValue = 100 - super.getValue
}
class Child extends TFirst with TSecond with CThird
In which order TFirst.getValue and TSecond.getValue should be called? Obviously CThird is already compiled and you can't change what the super for it is, so it has to be moved to the first position and there is already TSecond.getValue call inside it. But on the other hand this breaks the rule that everything on the left is base and everything on the right is child. The simplest way to not introduce such confusion is to enforce the rule that non-trait classes must go first.
The same logic applies if you just extend the previous example by substituting class CThird with a trait that extends it:
trait TFourth extends CThird
class AnotherChild extends TFirst with TSecond with TFourth
Again, the only non-trait class AnotherChild can extend is CThird and this again makes conflict resolution rules quite hard to reason about.
That's why Scala makes a rule much simpler: whatever provides the base class must come from the first position. And then it makes sense to extend the same rule upon the traits as well so if the first position is occupied by some trait - it also defines the base class.
1) Basically yes, your understanding is correct. Like in Java, every class inherits from java.lang.Object (AnyRef in Scala). So, since you are defining a concrete class, you will implicitly inherits from Object. If you check with the REPL, you got:
scala> trait Base1 {}
defined trait Base1
scala> trait Base2 {}
defined trait Base2
scala> class Sub extends Base1 with Base2 {}
defined class Sub
scala> classOf[Sub].getSuperclass
res0: Class[_ >: Sub] = class java.lang.Object
2) Yes, from the "Traits" paragraph in the specs, this applies also to them. In "Templates" paragraph we have:
The new supertype must have at least one constructor that does not take parameters
And then in "Traits" paragraph:
Unlike normal classes, traits cannot have constructor parameters. Furthermore, no constructor arguments are passed to the superclass of the trait. This is not necessary as traits are initialized after the superclass is initialized.
Assume a trait D defines some aspect of an instance x of type C (i.e. D is a base class of C). Then the actual supertype of D in x is the compound type consisting of all the base classes in L(C) that succeed D.
This is needed to define the base constructor with no-parameters.
3) As per answer (2), it's needed to define the base constructor

What do parentheses do after a class is called?

I have been trying to make a simple player class that contains all of the important player functions in python. I was just getting into the pygame module, when I noticed a class used parentheses. I took the time to learn what a class does in python, but, couldn't find why parentheses are used after for a class. Here is my main code.
class plr(pygame.sprite.Sprite):
def __init__(self):
plr.__init__(self)
self.image = pygame.Surface((20,20))
self.image.fill(black)
Any explanations?
The parentheses at the end of the line in a class statement surround the base classes of the class you're defining. In the common case, there's just one base class (which may be object if no other base class is needed). In Python 3, you can omit the base class and object will be used by default, but you should always explicitly name object (or some subclass) as a base in Python 2, or you'll get an "old-style" class which is something you probably don't want. (Old style classes are quite thoroughly obsolete and not worth learning about if you're new to Python. They don't exist any more in Python 3.)
Specifying a base class lets your new class inherit methods and other behavior from the base class. Inheritance is a key part of Object Oriented Programming, so you'll probably encounter it quite a bit!
In your specific example, the plr class is inheriting from pygame.sprite.Sprite. That means you can call Sprite methods on instances of plr, and they'll usually just work. You can override some of them, if you want to customize your object's behavior.
I do see an error in your code. The __init__ method you've written will recurse infinitely, since it calls plr.__init__, which is itself! You probably wanted it to call pygame.sprite.Sprite.__init__, which is overriding. You can make that call either with the long name I mentioned above, or by using super (which is nicer). Try:
class plr(pygame.sprite.Sprite):
def __init__(self):
super(plr, self).__init__()
...

Scala's sealed class "scope of seal"

I know that Scala allows to derive from sealed class if it is placed in the same file. May be there is a special construction or, if not, it makes sense to allow something like this:
sealed[Derived/*, list of allowed to derive*/] class Base
class Derived extends Base
This syntax will be like "Scope of protection":
class A{
private[A] val value = 10
}
So it will allow to place Derived class to separate file.
A sealed class cannot have any new subclasses added except the ones in the same file.
Reasons for the design
1 - The programmers only need to worry about the subclasses they already know about.
2 - You get better compiler support because the compiler will flag missing combinations of pattern with a warning message.

Scala: Do classes that extend a trait always take the traits properties?

Given the following:
class TestClass extends TestTrait {
def doesSomething() = methodValue + intValue
}
trait TestTrait {
val intValue = 4
val unusedValue = 5
def methodValue = "method"
def unusedMethod = "unused method"
}
When the above code runs, will TestClass actually have memory allocated to unusedValue or unusedMethod? I've used javap and I know that there exists an unusedValue and an unusedMethod, but I cannot determine if they are actually populated with any sort of state or memory allocation.
Basically, I'm trying to understand if a class ALWAYS gets all that a trait provides, or if the compiler is smart enough to only provide what the class actually uses from the trait?
If a trait always imposes itself on a class, it seems like it could be inefficient, since I expect many programmers will use traits as mixins and therefore wasting memory everywhere.
Thanks to all who read and help me get to the bottom of this!
Generally speaking, in languages like Scala and Java and C++, each class has a table of pointers to its instance methods. If your question is whether the Scala compiler will allocate slots in the method table for unusedMethod then I would say yes it should.
I think your question is whether the Scala compiler will look at the body of TestClass and say "whoa, I only see uses of methodValue and intValue, so being a good compiler I'm going to refrain from allocating space in TestClass's method table for unusedMethod. But it can't really do this in general. The reason is, TestClass will be compiled into a class file TestClass.class and this class may be used in a library by programmers that you don't even know.
And what will they want to do with your class? This:
var x = new TestClass();
print(x.unusedMethod)
See, the thing is the compiler can't predict who is going to use this class in the future, so it puts all methods into its method table, even the ones not called by other methods in the class. This applies to methods declared in the class or picked up via an implemented trait.
If you expect the compiler to do global system-wide static analysis and optimization over a fixed, closed system then I suppose in theory it could whittle away such things, but I suspect that would be a very expensive optimization and not really worth it. If you need this kind of memory savings you would be better off writing smaller traits on your own. :)
It may be easiest to think about how Scala implements traits at the JVM level:
An interface is generated with the same name as the trait, containing all the trait's method signatures
If the trait contains only abstract methods, then nothing more is needed
If the trait contains any concrete methods, then the definition of these will be copied into any class that mixes in the trait
Any vals/vars will also get copied verbatim
It's also worth noting how a hypothetical var bippy: Int is implemented in equivalent java:
private int bippy; //backing field
public int bippy() { return this.bippy; } //getter
public void bippy_$eq(int x) { this.bippy = x; } //setter
For a val, the backing field is final and no setter is generated
When mixing-in a trait, the compiler doesn't analyse usage. For one thing, this would break the contract made by the interface. It would also take an unacceptably long time to perform such an analysis. This means that you will always inherit the cost of the backing fields from any vals/vars that get mixed in.
As you already hinted, if this is a problem then the solution is just use defs in your traits.
There are several other benefits to such an approach and, thanks to the uniform access principle, you can always override such a method with a val further down in the inheritance hierarchy if you need to.

Using the override keyword on implementations of abstract methods

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.