edisonywh/behaves

Use default implementation in the Base class if its defined in the base class.

NavindrenBaskaran opened this issue · 3 comments

As of now the current behavior is if class B doesn't implement the #run function, it will fail.

class A
  extends Behave

  implements :run
end

class B
  extends Behave

  behaves_like A
end

What if we have something like this, class B behaves like A but lets say they have a common function with the same implementation logic, in that case class B don't necessarily have to implement the method #run again, so when an instance of class B invokes #run we will now call the function defined in class A.

class A
  extends Behave

  implements :run

  def run
    "run somewhere"
  end
end

class B
  extends Behave

  behaves_like A
end

b = B.new
b.run() -> invokes the function defined in A. # run somewhere

👋Hey Navin! Thanks for the issue.

Spot on! I'm actually working on a feature similar to this! Like you've pointed out, it's good to enforce behaviors, but sometimes you do want to inject some default behaviors.

My idea so far will make the API looks roughly something like this:

class Predator
  extend Behaves

  implements :kill, :hunt

  inject do
    def kill; puts "Killing"; end
    def hunt; puts "Hunting"; end
  end
end

This approach is a little different to the approach you pointed out, one difference is that this introduces a new inject method on the Behavior Object.

The main idea is to make the responsibility of the behaving object, very explicit. For example, with this API structure, you can very easily see:

  • What methods are required by looking at implements
  • What methods are injected by looking at inject

And now you still have to ability to define methods specific to Predator, which are not injected.

Keep in mind I still have not decided how to proceed with this as I'm still trying to come up with some more use cases, so feel free to throw in more ideas and I'm happy to discuss more!

I like this define methods specific to Predator, which are not injected, and i like the idea of inject too. I would like to contribute on this feature, can you let me know how can i start, since you said you have started working on a feature similar to this.

Sure, go ahead!

The idea would be something like this:

  • define an inject method for Behavior Object to use
  • capture the block being passed into the inject method, save it
  • execute the block that was saved earlier in the context of the Behaving Object.

Let me know if you face any issues! Looking forward to your contribution :)