Valerin
Valerin

Reputation: 475

scala - Inheritance

Any idea how I can avoid these repeated class parameters?

abstract class XClass(  var x:  Int, var y:  Int, var w:  Int, var h:  Int) {...}
abstract class MXClass( var xS: Int, var yS: Int, var wS: Int, var hS: Int) 
                        extends XClass (xS, yS, wS, hS)
class PXClass( var xP: Int = 0, var yP: Int = 0, var wP: Int = 0, var hP: Int = 0) 
                extends MXClass (xP, yP, wP, hP)
def draw(g: Graphics2D) {
g fillRect (x, y, w, h)
}

then I have something like this in a GUI:

  g setColor black
  val cc = new PXClass(200, 300, 10, 10)
  cc.draw(g)

So I am giving those parameters as they are needed in the GUI!

Thanks

Upvotes: 2

Views: 310

Answers (2)

Erik Kaplun
Erik Kaplun

Reputation: 38247

According to what you said:

the XClass is a Piece class and MXClass is a MovablePiece then PXClass is RectanglePiece class. Then I need Piece class to extend by StationaryPiece, thus I am trying to have some movable and statinary pieces in a BoardPanel of different shapes. – Val 18 mins ago

Let's just start out by defining them one by one — let's not use any inheritance because it's not immediately obvious it's even needed; you can come back to inheritance (or some other type of polymorphism) when needed but trust me it's never actually needed:

sealed trait                  Shape
case object Rectangle extends Shape
case object Square    extends Shape
case object Circle    extends Shape

case class Dimensions(x: Int, y: Int, w: Int, h: Int)

case class Piece(shape: Shape, dim: Dimensions, isMovable: Boolean = true)

val squarePiece =        Piece(Square,    Dimensions(x = 100, y =. 200, w = 20, h = 20))
val circularPiece =      Piece(Circular,  Dimensions(x = 0,   y = -100, w = 40, h = 40))
val immovableRectPiece = Piece(Rectangle, Dimensions(...), isMovable = false)

and then you can define a function to take any piece and draw it:

def draw(piece: Piece) = piece.shape match {
  case Rectangle => ...
  case Square =>    ...
  case Circle =>    ...
}

...and methods for binary functions:

case class Piece(...) {
  def collidesWith(other: Piece) = ...
  def overlapsWith(other: Piece) = ...
}

then:

draw(immovablePiece)

if (piece1 collidesWith piece2) ...

if (piece1 overlapsWith piece2) ...

You're free to make draw a method of Piece as well, but it doesn't really matter — if you manage to avoid inheritance, all methods become equivalent to plain functions anyway.

There is no need to use inheritance (i.e. subtype polymorphism); it's always best to start out with mathematically purer concepts and avoid extends altogether. If you consider the code I've demonstrated, you'll realise that it gives you a way to compose bits and pieces instead of providing monolithic types; it also allows you to convert one type of piece to another by providing an alternative value for an attribute — this is not possible with inheritance; it's not possible to change the type of an object once created.

val immovableCirclePiece = circularPiece.copy(isMovable = false)

Note that the Shape inheritance tree starting with that sealed trait is not the same as regular inheritance — what it does it defines an Algebraic Data Type, which in this case resembles quite closely what would be an enum in Java.


Furthermore, you could try to extract the data that is relevant to drawing/rendering and put it all in a, say, Representation class that holds both the Point as well as a rendering function to draw specific shapes. Feel free to ask for clarification — there's a lot to say and I'm only trying to get you started with designing your programs in a more sophisticated manner :)

Upvotes: 5

Anatoliy Kmetyuk
Anatoliy Kmetyuk

Reputation: 728

Just write:

class PXClass extends MXClass (0, 0, 0, 0) 

Upvotes: -2

Related Questions