0

Say I have this class and object hierarchy:

class A extends BB
class B extends BB
object A extends BB

abstract class BB {
   def writer: Writer (<say Writer is a custom class>)

   def write: {
       writer.<dothing>
   }
}

So writer has to be implemented in class A and B but not object A right in order for this code to work. Correct?

new A.write
new B.write

So writer has to be implemented in object A in order for this code to work. Correct?

A.write
Jwan622
  • 11,015
  • 21
  • 88
  • 181
  • I don't understand what you're asking. The structure of the "question" seems to be: *". Correct? . Correct?"*. In any case, you have to implement all missing methods when a concrete class is defined, not when objects of this class are instantiated, or when those methods are invoked. – Andrey Tyukin Jun 05 '18 at 20:17
  • 2
    @AndreyTyukin; You forgot __ – jwvh Jun 05 '18 at 20:21
  • Possible duplicate of [Difference between Abstract Class and Trait](https://stackoverflow.com/questions/2005681/difference-between-abstract-class-and-trait) and [Scala traits vs abstract classes](https://stackoverflow.com/questions/1991042/what-is-the-advantage-of-using-abstract-classes-instead-of-traits). – Andrey Tyukin Jun 05 '18 at 20:24
  • 1
    There is a misconception that `object C` implements companion `class C`, but that's only true if expressed explicitly, as in, `object C extends C`, which is an idiom. – som-snytt Jun 05 '18 at 21:06

1 Answers1

1

trait: is stateless, and class or object both can extend trait.

You define something as object when it does not have any states.

scala>     trait CanFly {
     |       def fly: String
     |     }
defined trait CanFly

scala>     class DuckCanFly extends CanFly {
     |       override def fly: String = "duck duck"
     |     }
defined class DuckCanFly

scala>     object EagleCanFly extends CanFly {
     |       override def fly: String = "eagle eagle"
     |     }
defined object EagleCanFly

scala> new DuckCanFly().fly
res0: String = duck duck

scala> EagleCanFly.fly
res1: String = eagle eagle

If you want companion object define it as below, you don't have to extend the trait again.

scala> :paste
// Entering paste mode (ctrl-D to finish)

    class DuckCanFly extends CanFly {
      override def fly: String = "duck duck"
    }

    object DuckCanFly {
      def apply(): DuckCanFly = new DuckCanFly()
    }

// Exiting paste mode, now interpreting.

defined class DuckCanFly
defined object DuckCanFly

scala> DuckCanFly().fly
res8: String = duck duck

In your example, you can define it as trait as I do not see any state, and you can define childs as object.

trait BB {
   def writer: Writer
   def write = writer.write()
}

object A extends BB {
   def writer: Writer = new AWriter()
}

object B extends BB {
   def writer: Writer = new BWriter()
}
prayagupa
  • 30,204
  • 14
  • 155
  • 192
  • Instead of "stateless", did you mean, "does not have constructor args?" – Tim Harper Jun 06 '18 at 21:22
  • @TimHarper correct, because constructor args represent state, (thats how I think in real world anyway :)) – prayagupa Jun 06 '18 at 21:24
  • Can a trait not have variables? – Tim Harper Jun 07 '18 at 01:50
  • 1
    @TimHarper `trait` can have variables (yes state) honestly stateless may not be a good way of defining trait at all. I think of state as how you can define `case class` but one can argue i can have state inside trait too `trait X { val x: Int }` which is weird still possible. will probably stick to constructor args. Thanks for correcting me. – prayagupa Jun 07 '18 at 02:18