scala - Case classes inheriting from abstract class

I'm currently learning Scala and I have some problems designing my case classes. I need two case classes that have the same properties. So I thought I would be a good idea to inherit from an abstract base class that defines these properties. However this code does not compile

abstract class Resource(val uri : String)

case class File(uri : String) extends Resource(uri)
case class Folder(uri : String) extends Resource(uri)

because uri in the case class constructors would overwrite the uri property of the base class.

What would be the correct way to design this?

I want to be able to do something like this

val arr = Array[Resource](File("test"), Folder("test2"))

arr.foreach { r : Resource => r match {
  case f : File => println("It's a file")
  case f : Folder => println("It's a folder")
} }

The "equivalent" Java code should be something like

abstract class Resource {
   private String uri;

   public Resource(String uri) {
       this.uri = uri
   }

   public String getUri() {
       return uri;
   }
}

// same for Folder
class File extends Resource {
    public File(String uri) {
        super(uri);
    }
}

2 Answers

  1. Leopold- Reply

    2019-11-13

    The correct syntax should be:

    abstract class Resource {
       val uri: String
    }
    
    case class File(uri : String) extends Resource
    case class Folder(uri : String) extends Resource
    
    
    Stream[Resource](File("test"), Folder("test2")) foreach { 
      r : Resource => r match {
       case f : File => println("It's a file")
       case f : Folder => println("It's a folder")
    } }
    

    EDIT

    Without case classes:

    abstract class Resource(val uri : String)
    
    class File(uri : String) extends Resource(uri) {
       override def toString = "..."
    }
    object File {
       def apply(uri: String) = new File(uri)
    }
    
    class Folder(uri : String) extends Resource(uri) {
       override def toString = "..."
    }
    object Folder {
       def apply(uri: String) = new Folder(uri)
    }
    
  2. Loren- Reply

    2019-11-13

    Make these two case class extends a common trait which define it interface and it should work.

    BTW, you need an identifier before the type clause in case statement.

    trait Resource {
        val uri: String
    }
    
    case class File(uri : String) extends Resource
    case class Folder(uri : String) extends Resource
    
    val arr = Array[Resource](File("test"), Folder("test2"))
    
    arr.foreach { r : Resource => r match {
      case s: File => println("It's a file")
      case s: Folder => println("It's a folder")
    }}
    

Leave a Reply

Your email address will not be published. Required fields are marked *

You can use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>