There exists (outside of my code)
trait Foo {
protected val bar = 0
}
I want have a class FooImpl that extends Foo and makes bar public.
I heard that subclasses could increase the visibility of their inherited members.
How do I do this?
I tried
class FooImpl extends Foo {
override val logger = super.logger
}
But got the error:
super may be not be used on value logger
It works if you make logger a def instead of a val.
trait Foo {
protected def logger = 0
}
class FooImpl extends Foo {
override val logger = super.logger
}
If Foo isn't defined by you, you may be out of luck outside of a solution involving reflection.
See this and this.
You could increase visibility of methods.
When you declare field with wider visibility you declare new field.
Related
Could someone explain why scala would allow a public variable, to satisfy the implementation of an abstract declared Protected item? My first assumption is that the compiler would complain, but I created a small test to see if this worked, and to my surprise it does. Is there an advantage to this? (perhaps this is normal in OOP?) Any methods to avoid the accidental pitfall?
object NameConflict extends App {
abstract class A {
protected[this] var name:String
def speak = println(name)
}
class B(var name:String) extends A { //notice we've declared a public var
}
val t = new B("Tim")
t.speak
println(t.name) // name is exposed now?
}
It's normal and as in Java. Sometimes it's desirable to increase the visibility of a member.
You can't do it the other way around and turn down visibility in a subclass, because the member can by definition be accessed through the supertype.
If invoking a method has terrible consequences, keep the method private and use a template method that can be overridden; the default implementation would invoke the dangerous method.
abstract class A {
private[this] def dangerous = ???
final protected def process: Int = {
dangerous
template
}
protected def template: Int = ???
}
class B extends A {
override def template = 5
}
A Java library class I'm using declares
protected getPage(): Page { ... }
Now I want to make a helper Scala mixin to add features that I often use. I don't want to extend the class, because the Java class has different subclasses I want to extend at different places. The problem is that if I use getPage() in my mixin trait, I get this error:
Implementation restriction: trait MyMixin accesses protected method getPage inside a concrete trait method.
Is there a solution how to make it work, without affecting my subclasses? And why is there this restriction?
So far, I came up with a work-around: I override the method in the trait as
override def getPage(): Page = super.getPage();
This seems to work, but I'm not completely satisfied. Luckily I don't need to override getPage() in my subclasses, but if I needed, I'd get two overrides of the same method and this work-around won't work.
The problem is that even though the trait extends the Java class, the implementation is not actually in something that extends the Java class. Consider
class A { def f = "foo" }
trait T extends A { def g = f + "bar" }
class B extends T { def h = g + "baz" }
In the actual bytecode for B we see
public java.lang.String g();
Code:
0: aload_0
1: invokestatic #17; //Method T$class.g:(LT;)Ljava/lang/String;
4: areturn
which means it just forwards to something called T$class, which it turns out is
public abstract class T$class extends java.lang.Object{
public static java.lang.String g(T);
Code:
...
So the body of the code isn't called from a subclass of A at all.
Now, with Scala that's no problem because it just omits the protected flag from bytecode. But Java enforces that only subclasses can call protected methods.
And thus you have the problem, and the message.
You cannot easily get around this problem, though the error message suggests what is perhaps the best alternative:
public class JavaProtected {
protected int getInt() { return 5; }
}
scala> trait T extends JavaProtected { def i = getInt }
<console>:8: error: Implementation restriction: trait T accesses
protected method getInt inside a concrete trait method.
Add an accessor in a class extending class JavaProtected as a workaround.
Note the last line.
class WithAccessor extends JavaProtected { protected def myAccessor = getInt }
trait T extends WithAccessor { def i = myAccessor }
works.
I need a smart mechanism for component composition which allows mixed in traits to initialize after the composed component. The following throws a NullPointerException:
class Component {
def addListener(pf: PartialFunction[Any, Unit]) {}
}
trait DynamicComponent {
protected def component: Component
component.addListener {
case x =>
}
}
class Foo extends DynamicComponent {
protected val component = new Component
}
new Foo // -> NullPointerException
The following things are not options for me:
Using protected lazy val component; that would produce an avalange of dozens of vals needing to become lazy, something I do not want.
Putting addListener in a method, e.g. initDynamic(); because I will be mixing in many traits, and I don't want to remember to call half a dozen initFoo() methods.
Using DelayedInit. This doesn't work with traits, at least according to the scaladocs.
I could live with a single init() call, but only under the following conditions:
all mixed in traits can easily declare to be invoked in this one single call
it is a compile error to forget the init() statement.
You can delay the initialization of a trait by by using early definitions. (See section 5.1.6 of the scala language specification)
class Foo extends {
protected val component = new Component
} with DynamicComponent
It's even clunkier than your solution, but you can always require the creation of a val that must be set with the init() method. You could choose to not do it last and get an error at runtime, but at least you won't forget it entirely:
class Component {
def addListener(pf: PartialFunction[Any, Unit]) {
println("Added")
}
}
trait Dyn {
protected def component: Component
protected val initialized: Init
class Init private () {}
private object Init { def apply() = new Init() }
def init() = { component.addListener{ case x => }; Init() }
}
class Foo extends Dyn {
protected val component = new Component
protected val initialized = init()
}
No cheating!:
> class Bar extends Dyn { protected val component = new Component }
<console>:12: error: class Bar needs to be abstract, since value
initialized in trait Dyn of type Bar.this.Init is not defined
class Bar extends Dyn { protected val component = new Component }
The advantage this has is if you need multiple things to be in place before you initialize all of them cooperatively, or if your Component class is final so you can't mix in anything else.
AN idea could be to use the trick described here:
Cake pattern: how to get all objects of type UserService provided by components
All your components that should be initialized could be registered in some Seq[InitializableComponent]. And then you could initialize all registered components with a foreach.
No component will be forgotten in that Seq because they are registered automatically, but you can still forget to call the foreach anyway...
Here is one idea (I am happy to read about other suggestions):
class Component {
def addListener(pf: PartialFunction[Any, Unit]) {
println("Added")
}
}
trait DynamicComponentHost {
protected def component: Component with DynamicPeer
protected trait DynamicPeer {
_: Component =>
addListener {
case x =>
}
}
}
class Foo extends DynamicComponentHost {
protected val component = new Component with DynamicPeer
}
new Foo
So basically I am forcing the component to mix in a type that can only be provided by the mixed in trait. Reasonable? Looks a bit too complicated in my eyes.
In Scala, if I create an object and companion class, identifiers declared with the protected modifier can be accessed from the class if the object is imported:
object Foo {
protected val X = 42
}
class Foo {
import Foo._
def getX(): Int = X
}
However, the protected identifier cannot be accessed from a subclass of the class Foo:
class Bar extends Foo {
import Foo._
def getX(): Int = X * 2
}
I get a compile-time error in Bar.
Other then (implied) public, is there any access modifier I can place on X so that it can be accessed from subclasses of its companion, but not from other classes, including other classes in the same package?
That's because only the class Foo is companion to the object Foo.
Here, the difference between private and protected meaningless, since the object Foo is a singleton, which means there isn't any other object that has the same class as object Foo (Foo.type).
Access restriction in Scala is package-based, so the short answer is no. You could make a forwarder on the base class, though, unless you need it to be available without an instance.
In your place, however, I'd go back to the design board.
In such cases, I would suggest using a package private modifier, like below:
object Foo {
private[your_package] val X = 42
}
The value will still be visible to everybody else in the package.
To achieve the same thing, One solution to this problem can be:
class Bar extends Foo {
import Foo._
override def getX(): Int = super.getX * 2
}
In Scala I can do this:
trait SomeTrait {
protected def foo: String
}
class Wibble extends SomeTrait {
protected var foo = "Hello"
}
But I cannot do the same thing where I provide a default definition for foo
trait SomeTrait {
protected def foo: String = "World"
}
class Wibble extends SomeTrait {
protected var foo = "Hello" //complains about lack of override modifier
override protected var foo = "Hello" //complains "method foo_ overrides nothing"
}
Why can't I do this?
EDIT: After a conversation on the scala-users mailing list, I have raised this in trac
In Scala, when you write a var foo, the Scala compiler automatically generates a setter (called foo_=) and a getter (called foo) for it, and sets the field as private (you'll see it as private if you decompile a class having 'public' Scala fields with javap). That's what the 'method foo_= overrides nothing' error means. In your trait you haven't defined a foo_= method, and for a public field setter and getters always come in pairs.
If you do not provide a default value in the trait (i.e. abstract method), then the override keyword is not necessary. Therefore, in your first example, the getter overrides the abstract method and the setter... it just is there. The compiler doesn't complain. But when you provide an actual implementation of the method in the trait, you need to specifically write the override keyword when overriding. When writing protected var foo, you haven't specified the override keyword for the getter and when writing override protected var foo, you have also indicated to the compiler that method foo_= is to be overridden, but the trait has no such method.
Also, logically you cannot really override a def with a var (considering a strict view of overriding, like in the previous paragraph). A def is logically a function (you give it some input, it produces an output). A var is similar to a no-arg function, but also supports setting its value to something else, an operation which is not supported by a function. Instead, if you would change it to a val, it would be OK. It's like a function that always produces the same (cached) result.
If you want to have similar behaviour to a var you could do something like this (by having explicit setter and getters):
class Wibble extends SomeTrait {
private var bar = "Hello"
override protected def foo = bar
protected def foo_=(v: String) { bar = v}
}
Now you can do anything you could do with a var :).
val x = new Wibble
println(x.foo) // yields "Hello"
x.foo = "Hello again"
println(x.foo) // yields "Hello again"