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.
Related
I want to extend a trait from Scala object and override those methods which are in trait. So my doubt is those methods will become static to that Object
or instance methods, and is this good approach to extend from trait to Scala Object. Please help on this
trait A{
def show:Unit
}
object B extends A{
override def show(): Unit = {
println("inside Object")
}
}
There are no static methods in Scala. object can indeed extend a trait. Overriden methods, like show, do not become static methods, instead they belong to a single instance of B.type. This is the singleton pattern provided by Scala's object definition facility.
Try the following in Scala REPL:
object B
B
It should output something like
res0: B.type = B$#5688722f
Note how the value B has type B.type, so B is just a value/instance, nothing to do with statics.
Hm, I think a common example/usecase of what you've just described is extending the App trait and overriding the main definition.
object test extends App
{
override def main (args: Array[String]): Unit = {
println("Hello, let's get started")
}
}
In general though, why don't you define the class itself to extend the trait?
If you are going to instantiate new instances of B using B() (instead of new B()) it makes sense to do this.
trait A{
def show:Unit
}
object B { // companion aka singleton object
def apply(){
...
}
}
class B extends A{
override def show(): Unit = {
println("inside Object")
}
}
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.
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.
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.
I'm having difficulties with the private annotation of inner class methods and constructors. While this works as expected:
trait A {
protected def lala = ()
}
trait B extends A {
lala
}
The following doesn't:
trait A {
class Lala protected()
}
trait B extends A {
new Lala
}
Neither does this:
trait A {
class Lala private[A]()
}
trait B extends A {
new Lala
}
The only way around is something like this:
object Screwed {
trait A {
class Lala private[Screwed]()
}
trait B extends A {
new Lala
}
}
Does Scala really fail here to provide a clear mechanism, or am I missing something? My guess would have been that it should be private[this.type] but scalac doesn't want to swallow that at all...
Well,
trait A {
class Lala protected()
new Lala
}
doesn't compile either. The error message seems pretty reasonable:
error: constructor Lala in class Lala cannot be accessed in trait A
Access to protected constructor Lala not permitted because
enclosing class trait A in object $iw is not a subclass of
class Lala in trait A where target is defined
Protected access means you can only access that constructor from that class or sub-classes. You're trying to call it from the enclosing trait. One thing you can do is this:
trait B extends A {
class Gaga extends Lala
new Gaga
}
I wouldn't expect your third example to compile, for similar reasons.
Also note the difference between a protected constructor and a protected class. So for example:
trait A {
protected class P
class U // unprotected
}
class B extends A {
new P // OK
new U // OK
}
val b = new B
new b.P // error
new b.U // OK
This also works with the desired visibility (Lala can only be instantiated from A or subtypes of A).
trait A {
class Lala private[A]()
protected def newLala = new Lala
}
trait B extends A {
newLala
}
I wonder what is the purpose of something like protected[A] if it doesn't work in this case.
the protected one should work for sure, what error do you get? for the private ones, the scope you define controls their visibility (so in a trait A, if you give visibility of A, it is obviously not visible in B). In the last example, you have given the scope as Screwed so anything inside Screwed would be able to see the private class. btw, I prefer to write the access modifiers as the first thing in a code line to facilitate easier reading
what version of scala are you using and what do you mean by "does not work" ?
HTH!