5

Google didn't help me with this question, I hope that doesn't mean it is not possible:

In my class I want to have a method that has a signature defined, but the body is not defined (method1)

There will be many defined methods that satisfy this signature (impl1, impl2, impl3)

When I initialise the object, I will then choose (based on some criteria) which method implementation impl1, impl2, impl3 to assign to the function pointer method1

Basically I'm asking how I can have a function pointer that can point to any function satisfying its signature.

EDIT:

So, it turns out it is actually very straight forward:

var method: Int => Int = (x => x+1)

method = (x => x-1)
method = (x => x*2)
etc...

My problem before was that I was using "val" or "def" to define "method"

Not sure why this wasn't suggested directly. Many people favoured the way of having the function as a parameter to some secondary class then initialise that class with a specific implementation. Maybe there is something that I'm missing.

EDIT 2: I realise now that I didn't get the answer I was looking for because I didn't word my question properly, I should have said that I wanted "delegate" behaviour as it is in C#.

6
  • 1
    Why not create an abstract class with the signature then 3 child classes with the three implementations? Commented Apr 29, 2014 at 12:14
  • 1
    Function composition is more powerful that simple inheritance. By considering your code (a function, here) as data you pass to your class/function/whatever, you have a more generic way to build the composed features you need. The answer proposed by Idan Arye is a great example IMO. Commented Apr 29, 2014 at 12:54
  • @Peter yes, I ran into that when I was trying to do it. The problem is that, this is a totally different approach to what I'm trying to do, which will make me change the way I design the code. I'm thinking there should be a way to do function pointers. Commented Apr 29, 2014 at 16:04
  • "Not sure why this wasn't suggested directly" because you did not mention you want this to be mutable :). You might take the fact that everyone proposed an immutable implementation as a hint to a more idiomatic solution. Also note that you can get the mutability when passing the function as parameter -- just make it a var and reset foo.func = ... if necessary. Commented Apr 29, 2014 at 17:45
  • @bluenote10 ok, let's assume everyone thought that I want it immutable. This solution I copied in my question was only presented by one person you and you used the immutable version. However, everyone else was wrapping the function in a class.. I just don't see why you would want to complicate things like that when you can just do it in a simple way. I'm trying to figure out if there is something I'm missing. Commented Apr 29, 2014 at 18:33

4 Answers 4

6

In Scala, functions are objects, so you can do:

class Foo(val func : Int => Int){
}
object Main{
    def main(args: Array[String]) {
        val foo1=new Foo(x => x + 1)
        val foo2=new Foo(x => x + 2)
        val foo3=new Foo(x => x + 3)
        println(foo1.func(10)) // Prints 11
        println(foo2.func(10)) // Prints 12
        println(foo3.func(10)) // Prints 13
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

That's an interesting way of doing it, thanks a lot !
1

And here is not-so-elegant approach with inheritance:

abstract class Foo() {
  def say(): String

  protected def bark = "Woof!"
  protected def quack = "Quack!"
}

val dog = new Foo() {
  def say() = bark
}

dog.say
// res2: String = Woof!

1 Comment

yeah, I ran into this while trying to figure out the solution. However, I would rather avoid doing this.
1

You mean like so:

class Whatever(selector: Int) {

  type Signature = Int => String

  private val implUsed = selector match {
    case 1 => impl1
    case _ => impl2
  }

  private val impl1: Signature = (i: Int) => i.toString
  private val impl2: Signature = (i: Int) => i.toString + "_suffix"

  def method: Signature = implUsed

}

You could obviously also write the impls as defs. Maybe a different approach based on inheritance may be preferrable though -- you may want to clarify what you are trying to achieve. While this approach is a literal solution to your request, it would be much more idiomatic to pass around the functions itself, like @Idan Arye suggested.

2 Comments

yeah, but then how would you reassign a different implementation to "method"?
I FOUND IT, just use "var" instead of "val"... my whole problem was that I was using "val" or "def" instead of using a "var"
-1

I would not use a method at all in this case. Just have a field that can be initialized to the specific function you want. Something like:

class Foo(val method1: Int => Int)

val doubler     = new Foo(2*)
val incrementer = new Foo(1+)
val absolute    = new Foo(_.abs)
val parity      = new Foo(_ % 2)
val doesNothing = new Foo(identity)

doubler.method1(-3)     // => -6
incrementer.method1(-3) // => -2
absolute.method1(-3)    // =>  3
parity.method1(-3)      // => -1
doesNothing.method1(-3) // => -3

2 Comments

Thanks, that's is an interesting workaround ! It could be actually a good idea in general to wrap all the different implementations in that same class.
Isn't this the same as Idan Arye suggested?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.