I have the following class model:
sealed abstract class Tile(val coordinate: Int, val isOccupied: Boolean) {
def isEmpty() : Boolean
def getPiece() : Option[Piece]
}
case class EmptyTile(coordinate: Int) extends Tile(coordinate, false) {
override def toString: String = "" +coordinate
override def isEmpty() = true
override def getPiece() = None
}
case class OccupiedTile(coordinate: Int, val piece: Piece) extends Tile(coordinate, true) {
override def toString = piece.toString
override def isEmpty = false
override def getPiece = Some(piece)
}
and I get the following error:
Error:(6, 22) overriding value coordinate in class Tile of type Int;
value coordinate needs `override' modifier
case class EmptyTile(coordinate: Int) extends Tile(coordinate, false) {
^
What am I doing wrong?
EDIT: Request to see Piece class, adding here:
import Alliance.Alliance
import PieceType.PieceType
abstract class Piece(val piecePosition: Int, val pieceType : PieceType, val alliance: Alliance) extends Movable {
}
object PieceType extends Enumeration {
type PieceType = Value
val PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING = Value
}
Your abstract class Tile declares a val coordinate, making this value publicly accessible. Your case class EmptyTile implicitly declares coordinate as a val as well (case class "magic"). Basically, your case class is effectively trying to override a value already provided by your abstract class.
You can either remove the val in your abstract class declaration, or not make EmptyTile and OccupiedTile case classes.
Edit: proposed alternative after comment:
trait Tile {
def coordinate: Int
def isOccupied: Boolean
def isEmpty() : Boolean = !isOccupied
def getPiece() : Option[Piece]
}
case class EmptyTile(coordinate: Int) extends Tile {
override def toString: String = "" +coordinate
val isOccupied = false
def getPiece() = None
}
case class OccupiedTile(coordinate: Int, val piece: Piece) extends Tile {
override def toString = piece.toString
val isOccupied = true
def getPiece = Some(piece)
}
case class automatically makes its arguments vals. This is why the argument coordinate to EmptyTile, understood as val coordinate, conflicts with the abstract class's val coordinate.
One way to fix this is to have coordinate and isOccupied be defined as abstract in Tile. Tile can even be a trait instead of an abstract class:
sealed trait Tile {
def coordinate: Int
def isOccupied: Boolean
...
}
case class EmptyTile(coordinate: Int) extends Tile {
def isOccupied = false
...
}
case class OccupiedTile(coordinate: Int, piece: Piece) extends Tile {
def isOccupied = true
...
}
Related
Assume I have a List of possibles Credit Card
val availableCreditsCard = List(MasterCardCreditCard, VisaCreditCard)
Both those classes extends a trait called CreditCard
Now, I want to create a method, called isValid that accept the trait CreditCard
Something like:
def isValid(creditCard: CreditCard): Boolean = {
creditCard match {
case t: MasterCardCreditCard => MasterCardCreditCardPayment.isValid(t)
case s: VisaCreditCard => VisaCreditCardPayment.isValid(s)
}
}
Both MasterCardCreditCardPayment and VisaCreditCardPayment extends a trait called CreditCardPayment.
So, now, my question is, what if I want to add a new possible CreditCard (Amex), with his own CreditCardPayment (AmexCreditCardPayment), but just change the list availableCreditsCard and doesn't touch the match/case inside the isValid method?
Is it possible to create dinamically this match/case based on the list availableCreditsCard?
EDIT
This is the CreditCardPayment trait.
trait CreditCardPayment[CreditCard] {
def isValid(creditCard: CreditCard): Boolean
def checkCVV(creditCard: CreditCard): Boolean
}
and an example of VisaCreditCardPayment
object VisaCreditCardPayment extends CreditCardPayment[VisaCreditCard] {
override def isValid(creditCard: VisaCreditCard): Boolean = {
val listValidCreditCard = loadFile()
listValidCreditCard.contains(creditCard)
}
//Implemented because it the trait, not necessary
override def checkCVV(creditCard: VisaCreditCard): Boolean = {
val listCreditCard = loadFile()
val cvvToCheck = creditCard.cvv
listCreditCard.exists(_.cvv == cvvToCheck)
}
}
Now, your suggestion is, inside the isValid method, use a case t => CreditCardPayment.isValid(t). This is not even actual possible, since CreditCardPayment is a trait :(
If you want it "dynamic", just use inheritance rather than implementing it "on the side":
sealed trait CreditCard {
def isValid: Boolean
}
class MasterCard extends CreditCard {
def isValid = MasterCardCreditCardPayment.isValid(this)
}
class Visa extends CreditCard {
def isValid = VisaCreditCardPayment.isValid(this)
}
Now, you can just do def isValid(c: CreditCard) = c.isValid, no need for any match statements to keep in sync.
And when you add Amex:
class Amex extends CreditCard {
def isValid = AmexCreditCardPayment.isValid(this)
}
The isValid(amex) will just work, nothing needs to be updated.
Complementing Dima's answer. Since, you always want to delegate the isValid logic to the appropriate Payment. I will present you two ways to do not redefine the method in each sub-class.
One method using F-Bounded Polymorphism, which will require quite a boilerplate code for each sub-class, and it is not completely typesafe - thus may not worth the work.
And the second using typeclasses, which will be more typesafe, and will require less boilerplate for each new card.
For a more detailed discussion about F-Bounded vs Typeclasses, read this article.
Using F-Bounded
sealed trait CreditCardPayment[CC <: CreditCard[CC]] {
def isValid(creditCard: CC): Boolean
def checkCVV(creditCard: CC): Boolean
}
object VisaCreditCardPayment extends CreditCardPayment[VisaCreditCard] {
private final val validCreditCards: List[VisaCreditCard] = ???
override def isValid(creditCard: VisaCreditCard): Boolean =
validCreditCards.contains(creditCard)
override def checkCVV(creditCard: VisaCreditCard): Boolean =
validCreditCards.exists(_.cvv == creditCard.cvv)
}
object MasterCreditCardPayment extends CreditCardPayment[MasterCreditCard] {
private final val validCreditCards: List[MasterCreditCard] = ???
override def isValid(creditCard: MasterCreditCard): Boolean =
validCreditCards.contains(creditCard)
override def checkCVV(creditCard: MasterCreditCard): Boolean =
validCreditCards.exists(_.cvv == creditCard.cvv)
}
sealed trait CreditCard[CC <: CreditCard[CC]] { self: CC =>
def paymentMethod: CreditCardPayment[CC]
def cvv: String
final def isValid: Boolean =
paymentMethod.isValid(this)
}
final class VisaCreditCard (override val cvv: String) extends CreditCard[VisaCreditCard] {
override final val paymentMethod: CreditCardPayment[VisaCreditCard] = VisaCreditCardPayment
}
final class MasterCreditCard (override val cvv: String) extends CreditCard[MasterCreditCard] {
override final val paymentMethod: CreditCardPayment[MasterCreditCard] = MasterCreditCardPayment
}
Using Typeclasses
sealed trait CreditCardPayment[CC <: CreditCard] {
def isValid(creditCard: CC): Boolean
def checkCVV(creditCard: CC): Boolean
}
sealed trait CreditCard {
def cvv: String
}
// Provides the 'isValid' & 'checkCVV' extension methods to any CredictCard.
implicit class CreditCardOps[CC <: CreditCard](val self: CC) extends AnyVal {
def isValid(implicit payment: CreditCardPayment[CC]): Boolean =
payment.isValid(self)
def checkCVV(implicit payment: CreditCardPayment[CC]): Boolean =
payment.checkCVV(self)
}
final class VisaCreditCard (override val cvv: String) extends CreditCard
object VisaCreditCard {
final implicit val VisaCreditCardPayment: CreditCardPayment[VisaCreditCard] = new CreditCardPayment[VisaCreditCard] {
final val validCreditCards: List[VisaCreditCard] = ???
override def isValid(creditCard: VisaCreditCard): Boolean =
validCreditCards.contains(creditCard)
override def checkCVV(creditCard: VisaCreditCard): Boolean =
validCreditCards.exists(_.cvv == creditCard.cvv)
}
}
final class MasterCreditCard (override val cvv: String) extends CreditCard
object MasterCreditCard {
final implicit val MasterCreditCardPayment: CreditCardPayment[MasterCreditCard] = new CreditCardPayment[MasterCreditCard] {
final val validCreditCards: List[MasterCreditCard] = ???
override def isValid(creditCard: MasterCreditCard): Boolean =
validCreditCards.contains(creditCard)
override def checkCVV(creditCard: MasterCreditCard): Boolean =
validCreditCards.exists(_.cvv == creditCard.cvv)
}
}
Using the typeclass approach you can also define the isValid method for CreditCards as a function instead.
(This way you do not need to define and import the CreditCardOps implicit / value class).
def isValid[CC <: CreditCard](cc: CC)(implicit payment: CreditCardPayment[CC]): Boolean =
payment.isValid(cc)
Let's say I have the following code for value classes:
class Meters(val x: Int) extends AnyVal {
def +(m: Meters): Meters = new Meters(x + m.x)
}
class Seconds(val x: Int) extends AnyVal {
def +(s: Seconds): Seconds = new Seconds(x + s.x)
}
Is there any way for me to remove duplication of the "+" methods?
Something kind of like:
abstract class Units[T <: Units[T]](val x: Int) extends AnyVal {
def +(other: T): T = T(x + other.x)
}
Except I can't inherit from value classes, and I definitely can't use T like a constructor.
You can use a universal trait with a type class, lets start defining the trait.
trait Sum[T <: Sum[T]] extends Any {
val x: Int
def +(other: T)(implicit evidence : FromInt[T]): T = evidence.fromInt(x + other.x)
}
Now we need a type class that tell us how to go from an integer to some type, lets define this and call it FromInt
trait FromInt[T] {
def fromInt(x: Int) : T
}
now lets define the Meters value class which is as simple as
class Meters(val x :Int) extends AnyVal with Sum[Meters]
and in the companion object we can provide an implicit value of the type class we defined.
object Meters{
implicit val intConstructable : FromInt[Meters] = new FromInt[Meters] {
override def fromInt(x: Int) = new Meters(x)
}
}
and now we can just do
val added = new Meters(2) + new Meters(3)
println(added.x)
I have a class with a generic type parameter and I would like to create an instance of this type using reflection. Moreover, the type has a private constructor.
Here is a code sample of the problem:
class X private (x: Int) {
}
class Y private (y: Int) {
}
abstract class Foo[T](z : Int) {
var bar : T = createInstance[T](z)
def createInstance[T](z: Int) : M = {
???
}
}
This would allow me to instantiate Foo and access bar:
class xFoo extends Foo[X]{
}
class yFoo extends Foo[Y]{
}
var xfoo = new xFoo(5)
println(xfoo.bar.x)
var yfoo = new yFoo(6)
println(yfoo.bar.y)
This should print out '5' and '6'.
I have tried using implicit in the following way.
def createInstance[T](z: Int)(implicit tag: TypeTag[T]) : T = {
val clazz = tag.tpe.getClass
val ctor = class.getDeclaredConstructor(classOf[Int])
ctor.setAccessible(true)
return ctor.newInstance(z).asInstanceOf[T]
}
However, then I get the error:
No TypeTag available for T
in line
var bar : T = createInstance[T](z)
Any suggestions? Thanks for your help!
Assuming that the super class does expose some method/value you're looking for like:
class X private(val x: Int) {}
You can extend it like so:
import scala.reflect._
class Foo[T](z : Int)(implicit ct: ClassTag[T]) {
var bar : T = createInstance[T](z)
def createInstance[T](z: Int) : T = {
val ctor = ct.runtimeClass.getDeclaredConstructor(classOf[Int])
ctor.setAccessible(true)
ctor.newInstance(Int.box(4)).asInstanceOf[T]
}
}
This enables you to call:
class XFoo(n: Int) extends Foo[X](n)
println((new XFoo(5)).bar.x)
My class inherits from some base class, and implements apply method with exactly the same signature as the base's one. I want to call base's apply method from my class.
When I try following:
class MyClass extends BaseClass {
def apply(k: String, v: String) = {
super.apply(k, v)
...
}
...
}
I got value apply is not a member of BaseClass... compile error.
How should I call base's apply method from the child class?
Also, why it is possible to override apply method without an override keyword?
EDIT: Actual code:
class OAuthParamsBuilder(helper: OAuthParamsHelper)
extends KeyValueHandler {
def apply(k: String, v: String): Unit = {
...
}
}
class OAuthInitSupportBuilder
extends OAuthParamsBuilder(StandardOAuthParamsHelper) {
/*override*/ def apply(k: String, v: String): Unit = {
super.apply(k, v)
...
}
...
}
EDIT: I've noticed that KeyValueHandler is a trait, this may be an issue.
trait KeyValueHandler extends ((String, String) => Unit)
You are not helping us help you, but I suspect this is the true definition of apply on the base class:
def apply(kv: (String, String)) = ???
EDIT
The code you pasted is not enough, as the problem is not reproducible with it:
trait OAuthParamsHelper
trait KeyValueHandler
class OAuthParamsBuilder(helper: OAuthParamsHelper) extends KeyValueHandler {
def apply(k: String, v: String): Unit = ???
}
object StandardOAuthParamsHelper extends OAuthParamsHelper
class OAuthInitSupportBuilder extends OAuthParamsBuilder(StandardOAuthParamsHelper) {
override def apply(k: String, v: String): Unit = {
super.apply(k, v)
???
}
}
i have a class that takes an implicit parameter which is used by functions called inside class methods. i want to be able to either override that implicit parameter and have both the class and its inherited parent class have a reference to the same new implicit object.
making the Parent implicit a var and setting that to a new value successfully overrides the implicit in the parent, but not the child.
(this is similar to scala: override implicit parameter to constructor, except there is the added restriction that the override affect both child class and parent class.)
for example:
def outside(implicit x: Boolean) {
println(x)
}
class Parent(implicit var x: Boolean) {
def setImplicit() {
x = true
}
def callOutside {
outside
}
}
class Child(implicit x: Boolean) extends Parent {
override def callOutside {
outside
}
}
and then:
scala> val a = new Parent()(false)
a: Parent = Parent#c351f6d
scala> a.callOutside
false
scala> a.setImplicit()
scala> a.callOutside
true // <-- sees the new implicit correctly
scala> val b = new Child()(false)
b: Child = Child#68331dd0
scala> b.callOutside
false
scala> b.setImplicit()
scala> b.callOutside
false // <-- wrong, desire "true" instead
is there any way to get the desired behavior? doing things like making both Parent and Child implicit be a var doesn't seem to work. thanks!
You could just
class Parent(x0: Boolean) {
implicit var x = x0
...
}
if you didn't really need the class parameter to be implicit. I'll assume that you do.
One alternative is to put the implicits on the companion object. Like so:
class Parent(x0: Boolean) {
implicit var x = x0
def setImplicit { x = true }
def outsideCall { outside }
}
object Parent {
def apply(implicit x: Boolean) = new Parent(x)
}
class Child(x0: Boolean) extends Parent(x0) {
def callOutside { outside }
}
object Child {
def apply(implicit x: Boolean) = new Child(x)
}
Alternatively, you could create a private main constructor for Child (decorated in some way so it's not ambiguous with the implicit) and use an implicit on a secondary constructor:
class Child private (b: Boolean, u: Unit) extends Parent()(b) {
def this()(implicit x: Boolean) = this(x,())
def callOutside { outside }
}