-1

I have come across this new method definition. Need explanation what exactly happens here.

Parent trait

sealed trait Generic{
 def name : String = name  // what is the body of this function call?
 def id : Int = id         
 def place : String = place
}

Child case classes

case class Capital( 
  countryName : String, 
  override val id: Int, 
  override val place:String
) extends Generic
  • warning: method place in trait Generic does nothing other than call itself recursively I get this warning message is there anything wrong in using these types of methods?
  • How exactly compiler treat these type of function calls def name : String = name?
  • Is it this call treats its body as its method name?
Puneeth Reddy V
  • 1,538
  • 13
  • 28
  • 2
    My guess is whoever wrote that is being cute. Trait members that are not overridden are given default values of infinite recursion, which is OK only if they are never referenced. – jwvh Mar 07 '18 at 08:51
  • @jwvh Being cute? that's sugar coding what I had in mind :) – Yuval Itzchakov Mar 07 '18 at 09:28
  • @jwvh I wrote that code it is working perfectly well and want to know `what is wrong with that syntax` and `how that syntax works`? For your reference https://stackoverflow.com/questions/49134848/sorting-a-list-of-generic-objects/49134964?noredirect=1#comment85296584_49134964 – Puneeth Reddy V Mar 07 '18 at 09:40
  • And I wrote that it is "infinite recursion," which is the answer to both of your questions: How does the syntax work? The method does nothing but call itself. What's wrong with it? Nothing, if what you want is a Stack Overflow exception when the method is called. If that's not what you want then that's what's wrong with it. – jwvh Mar 07 '18 at 09:59
  • @jwvh okay. Is there way to overcome this problem( stackoverflow exception ) other than using `???` as method body? – Puneeth Reddy V Mar 07 '18 at 10:08
  • 1
    @PuneethReddyV if you don't know how to implement it, then why do you want to have a method body in a trait in the first place? – Andrey Tyukin Mar 07 '18 at 10:10
  • I see two choices: 1-Leave `trait` members uninitialized. Every `class` that `extends` it will _have to_ provide their own implementation for those members. 2-Give the `trait` members default values that aren't so dangerous and that _might_ be useful/meaningful even if the derived `class` doesn't override it with a different implementation. – jwvh Mar 07 '18 at 10:16
  • @ Andrey Tyukin Please forward your solution iff you have better approach for this question https://stackoverflow.com/questions/49134848/sorting-a-list-of-generic-objects/49137912#49137912 – Puneeth Reddy V Mar 07 '18 at 10:33

2 Answers2

1

You are providing default implementations in the trait that are infinite loops, very much like in the following example:

def infiniteLoop: Unit = infiniteLoop

This is arguably the most useless and dangerous code that you could possibly put in a method of a trait. You could only make it worse by making it non-deterministic. Fortunately, the compiler gives you a very clear and precise warning:

warning: method place in trait Generic does nothing other than call itself recursively

  • "Is there anything wrong in using these types of methods"?: having unproductive infinite loops in your code is usually considered wrong, unless your goal is to produce as much heat as possible using computer hardware.
  • "How exactly compiler treat these type of function calls"?: Just like any other tail recursive function, but additionally it outputs the above warning, because it sees that it is obviously not what you want.
  • "Is it this call treats its body as its method name?": The body of each method declaration is what follows the =-sign. In your case, the otherwise common curly braces around the function body are omitted, and the entire function body consists only of the recursive call to itself.

If you don't want to have any unnecessary infinite loops around, simply leave the methods unimplemented:

sealed trait Generic{
  def name: String
  def id: Int
  def place: String
}

This also has the additional advantage that the compiler can warn you if you forget to implement one of these methods in a subclass.

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
0

Ok, so in your trait you define methods body via recursion. Means that these methods, if not overridden (and they should not as soon as you have defined them somehow), will call itself recursively till StackOverflowError happens. For example, you did not override name method in Capital, so in this case you get StackOverflowError at runtime:

val c = Capital("countryName", 1, "place")
c.name

So, you are warned, that you have recursive definition. Trait is sealed, so at least it cannot be overridden in other places, but anyway, such definition is something like put mines on your road and rely on your memory, that you will not forget about them (and anybody else will be care enough to check trait definition before extending)

Evgeny
  • 1,760
  • 10
  • 11