Confusion with interfaces

Hi,

suppose I have this

publicinterface OneVariableFunction{

publicdouble value(double x);

}

and then, I create another one:

publicinterface OneVariableFunctionDerivativeextends OneVariableFunction{

publicdouble derivative(double x);

}

and now I have a class that implements OneVariableFunctionDerivative:

publicclass Aimplements OneVariableFunctionDerivative{

//say f(x) = x*x -2=> df(x)/dx = 2*x

publicdouble derivative(double x){

return 2*x;

}

//the function f(x) = x*x -2

publicdouble value(double x){

return x*x-2;

}

}

So far so good. Now suppose I have another class

publicclass B{

public B(){

A a =new A();

someMethod(a);

}

void someMethod(OneVariableFunction f){

//The confusion is here! If OneVariableFunction extends OneVariableFunctionDerivative, why can't I do f.derivative(someDoubleValue)?

}

}

thanks in advance,

Manuel Leiria

[2465 byte] By [manuel.leiriaa] at [2007-11-26 20:18:23]
# 1

>void someMethod(OneVariableFunction f){

> //The confusion is here! If OneVariableFunction

> extends OneVariableFunctionDerivative, why can't I do

> f.derivative(someDoubleValue)?

>}

If OVF extended OVFD, you could indeed do that. But it doesn't. It's the other way around.

The compiler sees that you're passing a reference to an OVF, so it will only allow you to call OVF's methods. It can't know whether at runtime the reference you pass will actually point to an OVFD, so it can't be sure that method will be present.

jverda at 2007-7-10 0:41:58 > top of Java-index,Java Essentials,Java Programming...
# 2

Ok.Thanks.I've got it but it comes to me another question:

Does it make sense call the method

someMethod(a);

but declare the method as receiving an Object of type OVF

void someMethod(OneVariableFunction f){

...

}

I mean, I pass an object where I can access two methods but then declare the method as receiving OVF and so I have only access to one method!

thanks,

Manuel Leiria

manuel.leiriaa at 2007-7-10 0:41:58 > top of Java-index,Java Essentials,Java Programming...
# 3
You could use type casting if 'a' is really an OVDF object.
hiwaa at 2007-7-10 0:41:58 > top of Java-index,Java Essentials,Java Programming...
# 4

> Ok.Thanks.I've got it but it comes to me another

> question:

> Does it make sense call the method

>

> > someMethod(a);

>

>

> but declare the method as receiving an Object of type

> OVF

The compiler only knows about the reference type of the object whose method you're calling (B) and the reference type of the arg (A). It doesn't know what class the actual objects will be at runtime.

The type whose method your calling (B) determines the possible signatures. The type of the parameter (A) determines the exact signature that will be matched when the method is actually invoekd at runtime.

Runtime polymorphism comes into play in determining which class' method is actually called at runtime, but NOT for which signature to invoke.

If B had a subclass C that overrode that method, we could have:

B b = new C();

c.someMethod(f);

Even if C had a method that took OVFD, we'd still look at B at compile time, see that be only has a method that takes OVF (and OVFD IS an OVF, so it will match), then at runtime, look for the "deepest" class that implements that exact method--C.someMethod(OVF).

> I mean, I pass an object

You pass a reference.

> where I can access two

> methods but then declare the method as receiving OVF

> and so I have only access to one method!

Only one signature, but many possible classes' implementations of that exact signature.

jverda at 2007-7-10 0:41:58 > top of Java-index,Java Essentials,Java Programming...
# 5

> Only one signature, but many possible classes'

> implementations of that exact signature.

yes! Now I'm implementing an Secant Root Finder algorithm which doesn't use derivatives but later I'll need them when I implement Newton Root Finder (which uses the derivative of the function in the algorithm).

Thanks,

mleiria

manuel.leiriaa at 2007-7-10 0:41:58 > top of Java-index,Java Essentials,Java Programming...
# 6

> You could use type casting if 'a' is really an OVDF

> object.

That only helps if:

The class whose method you're calling (B) defines both signatures

AND

The declared reference type of the variable you're passing is OVF

AND

You know that at runtime that OVF reference will point to an OVFD (else ClassCastException).

If any of those conditions is false, the cast will be eithre pointless or dangerous.

jverda at 2007-7-10 0:41:58 > top of Java-index,Java Essentials,Java Programming...
# 7

> > You could use type casting if 'a' is really an

> OVDF

> > object.

>

> That only helps if:

>

> The class whose method you're calling (B) defines

> both signatures

>

> AND

>

> The declared reference type of the variable you're

> passing is OVF

>

> AND

>

> You know that at runtime that OVF reference will

> point to an OVFD (else ClassCastException).

>

>

> If any of those conditions is false, the cast will be

> eithre pointless or dangerous.

I understand that but class A was just an example. The class I'm using for now looks like this:

public class RootFunctions

{

/** tabela de funcoes global */

private static Map<String, OneVariableFunctionDerivative> TABLE = new Hashtable<String, OneVariableFunctionDerivative>(32);

// Introduz as funcoes na tabela

static {

enterFunctions();

}

/**

* Return the function with the given hash key

* @param key the hash key

* @return the function

*/

public static OneVariableFunctionDerivative function(String key){

return (OneVariableFunctionDerivative) TABLE.get(key);

}

/**

* @return um set de todas as chaves

*/

public static Set<String> getAllKeys(){

return TABLE.keySet();

}

/**

* Enter all the functions into the global function table.

*/

private static void enterFunctions(){

//Funcao f(x) = x^2 - 2

TABLE.put("x^2 - 2",

new OneVariableFunctionDerivative(){

/* Implementa o interface OneVariableFunction

* @param double x

* @return double

*/

public double value(double x) {

return x*x - 2;

}

/* Implementa a derivada

* @param double x

* @return double

*/

public double derivative(double x) {

return 2 * x;

}

});

//Funcao f(x) = x^2 - 4

TABLE.put("x^2 - 4",

new OneVariableFunctionDerivative(){

/* Implementa o interface OneVariableFunction

* @param double x

* @return double

*/

public double value(double x) {

return x*x - 4;

}

/* Implementa a derivada

* @param double x

* @return double

*/

public double derivative(double x) {

return 2 * x;

}

});

//Funcao f(x) = sin(x)

TABLE.put("sin(x)",

new OneVariableFunctionDerivative(){

/* Implementa o interface OneVariableFunction

* @param double x

* @return double

*/

public double value(double x) {

return Math.sin(x);

}

/* Implementa a derivada

* @param double x

* @return double

*/

public double derivative(double x) {

return Math.cos(x);

}

});

}

}

and who needs some function just come drink here, e.g,

public SomeClass

{

someMethod(RootFunctions.function("x^2 - 2"));

void someMethod(OneVariableFunction ovf){

//just need the functions value

}

someOtherMethod(OneVariableFunctionDerivative ovfd){

//Hmmm, here I'll need the derivative for some calculation

}

}

I think it's a good approach!

thanks for your tips,

mleiria

manuel.leiriaa at 2007-7-10 0:41:58 > top of Java-index,Java Essentials,Java Programming...