I have a trait:
trait Thing[B, A <: OtherThing[B]] {
...
private def SomeMethod() =
s"someString"
and some object that extends this trait:
object ImplementingThing extends Thing[SomeThing1, Something2] {
...
override def SomeMethod() =
s"SomeOtherFilePathString"
Is this possible? Or do I have to make the trait's private method public? If this can't be done, what's the reason behind this?
Also, quick unrelated question (I know, I know, but it saves me a post), what is the relationship between A and B as defined by the trait?
Private methods are invisible to both implementors and outside classes. As such, no, you cannot override a private method. For the same reasons, you also cannot have an abstract private method.
# trait Lol {
private val a: Int
}
cmd0.sc:2: abstract member may not have private modifier
private val a: Int
^
Compilation Failed
Protected methods, on the other hand, are visible to implementors but not to outside classes. Protected methods can be overridden.
Related
Let's say we have an abstract class (same question for traits also):
abstract class TypeParser[C <: Changes : TypeTag] extends Serializable {
val enrichmentType: EnrichmentType
protected def parseChanges(row: Row): C
}
Where implementations look like the following:
object PlaceholderParser extends TypeParser[PlaceholderChanges] {
val enrichmentType: EnrichmentType = PlaceholderType
override protected def parseChanges(row: Row): PlaceholderChanges = ???
}
The above implementation is a singleton, however, it can't be forced to be a singleton for future implementations. So one can simply implement it as a class, for example:
class PlaceholderParser2() extends TypeParser[PlaceholderChanges2] {
val enrichmentType: EnrichmentType = PlaceholderType2
override protected def parseChanges(row: Row): PlaceholderChanges2 = ???
}
Is there any way of forcing implementations to be a singleton?
side question: is there any advantage of forcing it?
To our advantage all objects extend an interface called Singleton.
You can't extend it directly but we can use a Scala feature called self-types to enforce that all subtypes of TypeParser to also be Singletons (i.e. objects)
abstract class TypeParser[C <: Changes : TypeTag] extends Serializable {
self: Singleton =>
...
}
If I have an abstract class, and want it to have two methods that are implemented by subclasses, and I don't want the methods to be visible outside the subclasses, how would I do this? I tried making the abstract methods protected and the implemented ones private, but keep getting errors. I need the method to be visible to the subclasses, and visible to nothing else.
It's sort of unclear, but the protected keyword should do what you want:
abstract class A() { protected[this] def f(): Unit }
class B() extends A() { protected[this] def f(): Unit = { println("B.f()") } }
val b = new B()
b.f() // error: value f is not a member of B
The trick is to make the def protected in the implementing class too, otherwise it will be public.
I would like to implement a trait with a self-type like the following:
trait HasEquipment {
this: {def loadEquipment: List[Equipment]} =>
//more methods
}
Now i can mix this trait into classes and these classes have to define a "loadEquipment" Method:
case class Course(id: Long) extends HasEquipment {
def loadEquipment: List[Equipment] = {
//implementation
}
}
However I don't want to expose to loadEquipment Method to everyone but only to the trait. So what i would like to do is make loadEquipment private in the Course class so that only the trait has access to it. Making it private prevents the trait from accessing the method.
Is there another way to make loadEquipment only accessible from within the trait?
Not sure why you want a self-type here. An abstract, protected member works just as well:
trait HasEquipment {
protected def loadEquipment: List[Equipment]
}
case class Course(id: Long) extends HasEquipment {
override protected def loadEquipment: List[Equipment] = ???
}
As a side note, structural types in Scala make use of reflection, which is the reason why they're usually avoided.
I read the section of Programming in Scala where abstract override is introduced, but I'm still confused by what exactly is signified by the joining of these modifiers. The snippet of code in which these modifiers is used is pasted below:
trait Doubling extends IntQueue {
abstract override def put(x: Int) { super.put(2 * x) }
}
In particular, I am confused by the purpose of abstract in this case, and why we cannot achieve the expected results simply with the override keyword. If we did not include a call to super, would we need the keyword abstract? Why or why not? I'm looking for a detailed explanation of this keyword combo as it pertains to stackable traits.
The reason is that the base class method is abstract
abstract class IntQueue {
def get(): Int
def put(x: Int)
}
If you were to not put abstract on the trait you end up with the explanation you were seeking:
trait Doubling extends IntQueue {
override def put(x: Int) { super.put(2 * x) }
}
<console>:9: error: method put in class IntQueue is accessed from
super. It may not be abstract unless it is overridden by a member
declared `abstract' and `override'
override def put(x: Int) { super.put(2 * x) }
So - you would need to mark the method as abstract.
Here is the "other side" of the equation: if the methods do have implementations then it is not necessary to mark the trait's method as abstract:
abstract class IntQueue {
import collection.mutable._
val q = Queue[Int]()
def get(): Int = { q.dequeue() }
def put(x: Int) = { q.enqueue(x) }
}
It is now unnecessary to include abstract
trait Doubling extends IntQueue {
/* Look Ma! no abstract here ! */ override def put(x: Int) { super.put(2 * x) }
}
defined trait Doubling
The idea is that it's an incomplete override -- you still want to require the eventually concrete implementation of the trait to provide that method, even though you're modifying that hypothetical method's behavior. In other words, the method you're overriding isn't a full standalone implementation. It gives a similar effect as a method decorator might in Python.
As far as I can reason, a method on a trait is abstract override if and only if it calls super, but it breaks encapsulation to expect the client of the code to inspect the implementation of the method to know it needs a concrete implementation. Therefore, you must mark it abstract override to fully define the interface.
A part of late binding in scala traits posts; provides a very clear explanation; provided verbatim bellow (read the full post for more info):
The abstract base class provided an implementation of the requestApproval method. This is good since the leftmost trait calls this method. What happens if the base class’s method is abstract?
abstract class ApprovalRequest {
def requestApproval()
}
If we change this, we get a rather odd message from the compiler:
error: method requestApproval in class ApprovalRequest is accessed
from super. It may not be abstract unless it is overridden by a member
declared abstract and override
The combination of abstract and override tells the compiler that the final implementation of the method will be provided by the class mixing-in the trait. If we add the abstract keyword to the methods, we can no longer use our anonymous implementation of ApprovalRequest. That object can’t be created since the abstract override methods will be looking for an implementation of requestApproval and there isn’t one. Instead we have to create a new class that extends ApprovalRequest and implements requestApproval. We then mix the traits into an instance of that class.
class ApprovalDelegate extends ApprovalRequest {
override def requestApproval() {
println("and now we play the waiting game")
}
}
val adCampaign = new ApprovalDelegate with MarketingApprovalRequest
with FinanceApprovalRequest with ExecutiveApprovalRequest
Which will now give the output:
requesting approaval from executives
requesting approval from Finance
requesting approval from Marketing
and now we play the waiting game
Consider the following:
trait TestTrait {
def doStuff()
}
final class TestClass {
// ...
}
I would like to instantiate an instance of TestClass that implements the method in the trait. The following does not compile:
// Illegal inheritance from final class TestClass
val t = new TestClass with TestTrait {
def doStuff() {
println("doing stuff")
}
}
This makes sense, since the anonymous class created would extend the final class. What I'm really after is an anonymous implementation of the trait mixed in to an instance of the final class.
The following works, but seems a bit roundabout. Is there a way to do this directly without the declared trait implementation?
trait TestTraitImpl extends TestTrait {
def doStuff() {
println("doing stuff")
}
}
val t = new TestClass with TestTraitImpl
As it turns out, you can't do the latter either.
final class TestClass
trait TestTrait
val t = new TestClass with TestTrait
Apparently, any Foo with Bar is creation of a new anonymous type, and thus final classes cannot have traits as mixins. This adds a great deal of theoretical significance to making a class final, as it prevents not just the concept of inheritance, but also stackable modification.
Method resolution rules are different in the two cases. In the first case an anonymous class is constructed first by whatever happens to be the methods/attributes of the type:
final class TestClass with TestTrait
and then you are trying to override a method of that, which conflicts with the final qualifier of TestClass.
In the second case you explicitly specify that you are overriding TestTrait behavior, and then the overriden behavior is mixed into TestClass.
I think it's perfectly fine to use the second method, and that it conveys more clearly what the intention is.