Reputation: 55569
Lately I've found myself working with different objects with similar structures (using play framework, but that's not really important) that I would like to store as different classes. They'll often have CRUD methods that are fundamentally the same, so I would like each of these classes to inherit from an abstract type to cut down on code duplication. The problems I'm running into are: 1.) Being able to return the sub-type, and 2.) Accessing fields of the sub-type within these abstract methods.
I was successfully able to get this working (in a more fleshed-out version) with get
methods taking advantage of apply
, but now I've hit a wall. This is a highly simplified version to express my problem, so the implementation of create
has been cut down. (The actual create method needs to access the object's fields, sending them to a database, etc..)
abstract class FileSystemObject(id: Int, path: String)
trait FileSystem[T <: FileSystemObject] {
val table: String
def apply(id: Int, path: String): T
def create(obj: T): Option[T] = Some(apply(1, obj.path))
}
case class File(id: Int, path: String) extends FileSystemObject(id, path)
object File extends FileSystem[File] {
val table: String = "files"
}
.. Which results in error: value path is not a member of type parameter T
At this point, it seems the solution I've chosen is horribly flawed, but I don't know how to proceed from here.
Upvotes: 1
Views: 340
Reputation: 52681
You need path
to be accessible on FileSystemObject
in order for it to be seen on T
. Try making it a def
that gets overridden by the concrete class:
abstract class FileSystemObject {
def id: Int
def path: String
}
case class File(id: Int, path: String) extends FileSystemObject
Upvotes: 4