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"
Related
Is there a way to invoke a function by default before any other function in a class is called?
I do not want to use frameworks and want to implement in pure Scala.
What I wanted to do is have some function in a class which checks if a user has access to the called method when a method of the same class is called.
This is done in a straightforward way with a private constructor, custom apply and companion object.
case class Foo private (bar: Bar){
def methYouWantToCall: Unit = ???
}
object Foo {
def apply(bar: Bar): Foo = {
val foo = new Foo(bar)
foo.methYouWantToCall
foo
}
}
Hence methYouWantToCall should be sideffecting function with Unit return type.
As you use scala, there are plenty of means of avoiding such ones.
I can extend my Scala class Foo with additional methods via an implicit class:
trait Foo {
def bar: String
}
object FooExtensions {
object implicits {
implicit class FooOps(foo: Foo) {
def baz: String = "baz"
}
}
}
But can I mock out those methods?
import org.mockito.Mockito
import org.scalatest.WordSpec
import org.scalatest.mockito.MockitoSugar
class MySpec extends WordSpec with MockitoSugar {
"My mock" should {
"handle methods from implicit classes" in {
import FooExtensions.implicits._
val foo = mock[Foo]
Mockito.when(foo.baz).thenReturn("bix") // fails at runtime
}
}
}
This compiles, but fails with
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
Is it possible to mock methods added via implicit classes? Hopefully with Mockito (or mockito-scala) but I'm interested in any approach that works.
Thing about extension methods, is that they are basically a syntactic sugar:
trait Foo
implicit class ExtensionMethods(foo: Foo) {
def bar: String = "bar
}
foo.bar
is equal to
new ExtensionMethods(foo).bar
So mocking:
Mockito.when(foo.bar).thenReturn("bix")
becomes:
Mockito.when(new ExtensionMethods(foo).bar).thenReturn("bix")
I think there is no workaround - perhaps PowerMock could let you change class constructor..., but with normal Mockito it is impossible.
Usually, it is not a problem though. That is because either:
you put into extension methods behavior, that only depends on extended value and passed parameters (and extended method is quite often pure function that doesn't require mocking) - if you want to change something there, you change input,
if behavior should change, you implement it inside a type class, and make extension method use that type class to inject behavior
trait Bar {
def bar: String
}
object Bar {
implicit val defaultBar: Bar = new Bar { def bar = "bar" }
}
implicit class ExtensionMethods(foo: Foo) {
def bar(implicit bar: Bar): String = bar.bar
}
// in test
implicit var overridenBar: Bar = ...
assert(foo.bar === "sth")
On a side note: the more functional you'll get the less you'll need to mock things as everything will depend only on input passed inside, and a cascade of mocks will become just a code smell - too tight coupling, too large interfaces, etc. Problem is that many Java libraries do not even follow SOLID principles, which makes them both hard to use/test with FP as well as bad OOP on its own. I'm telling this in case you feel mocking is the only way to go in your case.
The only way to achieve that is to use implicit conversions rather than implicit classes
This is a hack intended to show how this could be achieved, but I'd urge to take a look at the code and see why you actually need to do this
So, following your example, you could modify the code to look like this
trait Foo {
def bar: String
}
object FooExtensions {
object implicits {
implicit fooToOps(foo: Foo): FooOps = new FooOps(foo)
class FooOps(foo: Foo) {
def baz: String = "baz"
}
}
}
and your test
import org.scalatest.WordSpec
import org.mockito.MockitoSugar
class MySpec extends WordSpec with MockitoSugar {
"My mock" should {
"handle methods from implicit classes" in {
val fooOps = mock[FooOps]
implicit fooToOps(foo: Foo): FooOps = fooOps
val foo = mock[Foo]
when(foo.baz) thenReturn "bix" // works
}
}
}
the other thing to consider is that in your production you need to get an implicit parameter of the shape Foo => FooOps so when you call that method from the test the actual implicit mock is provided...
As I said, you can make it work like this, but I agree with Mateusz that you shouldn't need to
I would like to define trait that has const property, for example:
trait InitialTest {
// property would be set here or somewhere else, let's call it typeNumber
override def toString = typeNumber.toString
}
then I would like to set this value for each implementation like:
case class InitialTest1 extends InitialTest {
// set value here like typeNumber = 4
}
For each toString function would use impelemetation from trait.
Do you know how can I acheive it?
The easiest way of achieving it, that I see is:
trait MyTrait {
val myProperty: X // abstract property
override def toString: String = myProperty.toString
}
It would force implementation of the property:
class Impl extends MyTrait {
val myProperty = new X // without that line it doesn't compile
}
From there on, one might complicate design further e.g. by splitting the trait with the property from the trait overriding toString with a cake pattern (though I'd be vary about it).
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
}
Are there public instance variables anymore in Scala? I'm reading Programming in Scala, which covers Scala 2.8. If I'm understanding it correctly, it claims that vars in 2.8 are by default public.
I'm trying to write code for 2.9.1.final now, and instance variables are now by default private? But there's no public keyword that I'm aware of. (Interestingly enough, it appears it used to exist sometime in the 2.x series, but it mysteriously disappeared somewhere along the line.)
Am I missing something obvious?
Also, by extension, is there an easy way to declare a variable passed to a class constructor to be public (since it appears that those also have default private visibility now too)?
Example:
class Instance(label: String, attributes: Array[Int]){
val f = 0
}
Eclipse claims that label, attributes, and f are all private. Scala 2.9.1.final is being used as the library.
In scala, if you omit the modifer, then instance fields are public by default:
scala> class Foo { var foo = 1 }
defined class Foo
scala> class Bar { def bar() = { val f = new Foo; f.foo = 5; }}
defined class Bar
No worries there. However, when you use a variable in a constructor, the variable is not necessarily turned into a field:
scala> class Foo(foo: Int)
defined class Foo
scala> class Bar { def bar() = { val f = new Foo(5); println(f.foo) }}
<console>:8: error: value foo is not a member of Foo
class Bar { def bar() = { val f = new Foo(5); println(f.foo) }}
^
so you can declare it as a val or var to have it available:
scala> class Foo(val foo: Int)
defined class Foo
scala> class Bar { def bar() = { val f = new Foo(5); println(f.foo) }}
defined class Bar
Note that all fields are actually private, but scala exposes accessor methods (foo() and foo_=(t: Int)) to enable you to access the fields), which is why scala-ide says that the fields are private (assuming you mean when you hover over the variable).