Search code examples
scalainheritancecompanion-object

Scala - duplicated hierarchy for companion object


I'm pretty new to Scala, and I was wondering which is the best way to organize the hierarchy for classes and their companion objects.

Suppose that I have a base class or interface that I want to extend. In Python I'd do something like this:

class Base(object):
    def an_instance_method(self):
        return 0

    @classmethod
    def a_class_method(cls):
        return 1

    def another_instance_method(self):
        raise NotImplentedError()

    @classmethod
    def another_class_method(cls):
        raise NotImplementedError()

class A(Base):
    def another_instance_method(self):
        return self.an_instance_method() + 1

    @classmethod
    def another_class_method(cls):
        return cls.a_class_method() + 1

class B(Base):
    def another_instance_method(self):
        return self.an_instance_method() + 2

    @classmethod
    def another_class_method(cls):
        return cls.a_class_method() + 2

My current Scala solution is the following:

trait Base {
  def an_instance_method(): Int = 0
  def another_instance_method(): Int
}

trait BaseCompanion {
  def a_class_method(): Int = 1
  def another_class_method(): Int
}

class A extends Base {
  override def another_instance_method(): Int = an_instance_method() + 1
}
object A extends BaseCompanion {
  override def another_class_method(): Int = a_class_method() + 1
}

class B extends Base {
  override def another_instance_method(): Int = an_instance_method() + 2
}
object B extends BaseCompanion {
  override def another_class_method(): Int = a_class_method() + 2
}

Is there a better way?


Solution

  • For example in Shapeless you can find traits

    • ProductTypeClass and ProductTypeClassCompanion,

    • LabelledProductTypeClass and LabelledProductTypeClassCompanion.

    https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/typeclass.scala

    So I guess naming and organizing hierarchies are ok although you don't provide details how you use connection between class A and object A, class B and object B. Now they seem to be independent so an object A now can be not necessarily the companion object of class A and just some object A1.

    Actually I don't think this is redundant since these two hierarchies are two different ones. Class A and its companion object A are completely different and not connected in sense of inheritance and typing (Class companion object vs. case class itself), the only specific is that they can see members of each other.