Function calls...

R

Raymond Martineau

In C, it's possible to create an array of the following data structure to
associate a function call with a specific key or identifier:

struct {
char *key;
void (*function)();
} a[] = { { "Function1", Function1} ,
{ "Function2", Function2}};

(Or some other varient that you are comfortable with.)

I would like to know the appropriate procedure on how to implement the same
in Java. I would prefer to use the above system, as it can be much quicker
to call a function by looking up the associated token in a hashtable as
opposed to writing many lines of an if/else ladder.

The first thought that appeared in my mind would involve reflecting
classes. Checking with the API spec indicated that it should work, but I'm
not sure that placing a large number of methods in one class is the best
solution.

In case you're wondering, I'm using this system to interpret a language
that uses a large number of keywords (with each keyword executing its own
function.)
 
N

Nicky

Hi

Reflection is not very fast.
Another solution is to create an abstract class with a single method:

public abstract class AbstractFunction {
public abstract void execute();
}

and to extend and implement that class for each function:

public class Function1 extends AbstractFunction {
public void execute() {
// Code for function1
}
}

Hope it helps
Nicky
 
T

Tony Morris

Nicky said:
Hi

Reflection is not very fast.
Another solution is to create an abstract class with a single method:

public abstract class AbstractFunction {
public abstract void execute();
}

Abstract classes should never be used as a pure virtual type (with only
abstract methods), or a concrete type (with no abstract methods).
It is arguable that abstract classes should be used at all (inheritance from
anything but an interface is pure evil, but that's another story for another
camp fire).

In the case of an attempt to use an abstract class as a pure virtual type as
has been suggested, an interface is always more suited.
 
T

Tony Morris

Tony Morris said:
Abstract classes should never be used as a pure virtual type (with only
abstract methods), or a concrete type (with no abstract methods).
It is arguable that abstract classes should be used at all (inheritance from
anything but an interface is pure evil, but that's another story for another
camp fire).

In the case of an attempt to use an abstract class as a pure virtual type as
has been suggested, an interface is always more suited.

It's worth nothing that a common web application framework, known as Struts
(struts.apache.org last I checked), makes use of this antipattern.
Struts is reknowned for its 'crustiness' for this, and many other, reasons.
 
L

Lee Fesperman

Raymond said:
In C, it's possible to create an array of the following data structure to
associate a function call with a specific key or identifier:

struct {
char *key;
void (*function)();
} a[] = { { "Function1", Function1} ,
{ "Function2", Function2}};

(Or some other varient that you are comfortable with.)

I would like to know the appropriate procedure on how to implement the same
in Java. I would prefer to use the above system, as it can be much quicker
to call a function by looking up the associated token in a hashtable as
opposed to writing many lines of an if/else ladder.

The first thought that appeared in my mind would involve reflecting
classes. Checking with the API spec indicated that it should work, but I'm
not sure that placing a large number of methods in one class is the best
solution.

In case you're wondering, I'm using this system to interpret a language
that uses a large number of keywords (with each keyword executing its own
function.)

Reflection will work but is not the best choice here. In Java, you would normally use an
object reference instead of a function pointer. The object's class would implement an
interface containing the common method signature. This is quite efficient as opposed to
reflection and provides additional OO capabilities vs. a function pointer.
 
C

Chris Uppal

Raymond said:
In case you're wondering, I'm using this system to interpret a language
that uses a large number of keywords (with each keyword executing its own
function.)

For such an application, I think that the best way to go would be to use lots
of little objects that all have different implementations of the same generic
method.

E.g (non-compliable stripped down pseudo-Java):

=====
abstract class Action { void doIt(); }
class Action1 extends Action { void doIt() { /* something */} }
class Action2 extends Action { void doIt() { /* something */} }
....

Map actions = new HashMap();

actions.add("Action1", new Action1());
actions.add("Action2", new Action2());
.....
=====

In practise I would probably use anonymous inner classes rather than explicitly
naming each subclass. The effect is identical, but it would help keep the
source looking somewhat tighter. (But also make it harder to see what's going
on, which is why I used explicit classes in the above example).

-- chris
 
P

Peter Sestoft

In C, it's possible to create an array of the following data structure to
associate a function call with a specific key or identifier:

struct {
char *key;
void (*function)();
} a[] = { { "Function1", Function1} ,
{ "Function2", Function2}};

(Or some other varient that you are comfortable with.)

I would like to know the appropriate procedure on how to implement the same
in Java. I would prefer to use the above system, as it can be much quicker
to call a function by looking up the associated token in a hashtable as
opposed to writing many lines of an if/else ladder.

public interface Fun {
void call();
}
public Pair {
public final String key;
public final Fun fun;
public Fun(String key, Fun fun) {
this.key = key; this.fun = fun;
}
}

Pair[] a =
{ new Pair("Function1",
new Fun() {
public void call() { ... body of Function1 ... }
}),
new Pair("Function2",
new Fun() {
public void call() { ... body of Function2 ... }
}),
...
}

If you build a hash map the array like this:

Map<String,Fun> action = new HashMap<String,Fun>();
for (Pair p : a)
action.put(p.key, p.fun);

you get very fast execution of each instruction:

action.get(keyword).invoke();

Peter
 
A

Andrew McDonagh

Nicky said:
Hi

Reflection is not very fast.
Another solution is to create an abstract class with a single method:

public abstract class AbstractFunction {
public abstract void execute();
}

and to extend and implement that class for each function:

public class Function1 extends AbstractFunction {
public void execute() {
// Code for function1
}
}

Hope it helps
Nicky


Sipped

The usual name for this is 'Command pattern', however, like Tony said,
the AbstractFunction class should always be an interface.

So.

public interface Command {

void execute();

}

public class KeywordCommandTwo implements Command {


public void execute() {
...
}

}

public class KeywordCommandOne implements Command {


public void execute() {
...
}

}


And this code can be used like this....

public class Foo {

private Map keywordCommands = new HashMap();

public int main(String[] args) {


keywordCommands.put(keywordOne, new KeywordCommandOne());
keywordCommands.put(keywordTwo, new KeywordCommandTwo());


// load each keyword from file and execute its command.
for each keyword in file {
KeywordCommand command = (KeywordCommand)
keywordCOmmands.get(keyword);

command.execute();
}

}

}
 
R

Ryan Stewart

Tony Morris said:
Abstract classes should never be used as a pure virtual type (with only
abstract methods), or a concrete type (with no abstract methods).
It is arguable that abstract classes should be used at all (inheritance
from
anything but an interface is pure evil, but that's another story for
another
camp fire).
I'll bite. Why never use abstract classes?
 
A

Andrew McDonagh

Ryan said:
I'll bite. Why never use abstract classes?

in Java, they are the 'same' as in they tell you that a given any
derived/implementing class has those particular methods and also can be
substituted when the interface/abstract class type is used as the
referencing type.

However, in java a class can only have one base class, but can implement
many different interfaces at the same time.

It comes down to cohesion and coupling.

In C++ pure virtual abstract classes are just about the same...(ignoring
the differences ;- )
 
U

Ulf Nordlund

Andrew McDonagh skrev:
in Java, they are the 'same' as in they tell you that a given any
derived/implementing class has those particular methods and also can be
substituted when the interface/abstract class type is used as the
referencing type.

However, in java a class can only have one base class, but can implement
many different interfaces at the same time.

It comes down to cohesion and coupling.

In C++ pure virtual abstract classes are just about the same...(ignoring
the differences ;- )

I don't understand Andrew's explanation on why abstract classes
shouldn't be used... Are there any *practical* reasons why they should
be avoided? (An example?)
/ulf
 
A

Andrew McDonagh

Take for example the JTable swing component.

It displays the data contained within a TableModel. However, TableModel
is an interface - not a class.

This allows us to implement the same TableModel interface in any way we
like, and then give our own specialized model to the Jtable. JTable
does not need to know about or even guess how the tableModel is actually
implemented.

If JTable only ever knew about the abstract classes, then it would be
assuming that ALL tableModels were of the same base type, having the
same base implementation.

However, most tableModels do NOT have the same base type or are
implemented in the same way. Because JTable uses a generic TableModel
interface, we can implement it however we like. For example, we may have
a ODBC class that Implements the TableModel interface. Or a class that
gets its data from XML and implements the TableModel interface so that
JTable can 'see' the data.

Now for convenience, Java provides a range of off-the-shelf classes
which do most of the grunt work :

public abstract class AbstractTableModel implements TableModel {
....
}


public class DefaultTableModel extends AbstracttableModel {
....
}

etc.

But these 'assume' how most tableModels would work, but they may not be
appropriate for ours.

Its all about having a flexible design - anyone can implement an one or
more interfaces at the same time, but all Java objects can only ever
have one base class.

HTH

Andrew
 
S

Sudsy

Andrew said:
Ryan Stewart wrote:

in Java, they are the 'same' as in they tell you that a given any
derived/implementing class has those particular methods and also can be
substituted when the interface/abstract class type is used as the
referencing type.

However, in java a class can only have one base class, but can implement
many different interfaces at the same time.

So Sun obviously made a huge mistake with the java.awt.event.XXXAdapter
classes! Sorry, but I don't buy into "absolutes". The example I provided
actually serves an important role in GUI development. It's a lot easier
(and cleaner) to write something like this:

addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e ) {
System.exit( 12 );
}
} );

than have the class implement the WindowListener and have 6 out of the
7 methods be empty. YMMV
 
A

Andrew McDonagh

I don't quite understand the problem you (seem) to have, maybe I'm
mis-reading your words...but


Sun, myself and others have no problem with adapter classes. Sun made
these adapter classes available because lots of people only need to
implement specific parts of the interface, not all of them.

By having a single WindowListener interface it saved having to have
multiple specific event listener interfaces.

The adapter pattern is great for this.

However, the Sun code isn't designed to reference objects by the
xxxAdapter type, it references via the Interface the adapters (stub)
implement.

Andrew
 
C

Chris Smith

Andrew McDonagh said:
Take for example the JTable swing component.

It displays the data contained within a TableModel. However, TableModel
is an interface - not a class.

This example, of course, quickly reaches ad absurdum, as do most
examples of this pseudo-truth. Where this leaves the practical world is
when you start looking at specific examples:
However, most tableModels do NOT have the same base type or are
implemented in the same way. Because JTable uses a generic TableModel
interface, we can implement it however we like. For example, we may have
a ODBC class that Implements the TableModel interface. Or a class that
gets its data from XML and implements the TableModel interface so that
JTable can 'see' the data.

Except, of course, that you'd never want your database access code or
XML parsing code to be aware of Swing. Here's where it *does* come down
to coupling. It's better for thise data-access and parsing code to
provide a generic interface that's usable by anyone, rather than
something specific to the Swing GUI API. As a result, you get the
frequent pattern of a model adapter; that is something like:

public class XMLTableModel implements TableModel
{
public XMLTableModel(org.w3c.dom.Document doc) { ... }
...
}

And, since that class has no purpose other than to adapt data to Swing's
TableModel, it wouldn't naturally extend any other class and suddenly
ceases to make a good example of why something might want to extend some
other class and also implement TableModel. In fact, it turns out that
any linking of an underlying data source with an Swing model interface
is best accomplished by composition rather than inheritance.

The example also extends to many other uses of interfaces. The only
time it doesn't apply, in fact, is when an interface exists in the core
part of the standard API (for example, java.lang) and is therefore
automatically a dependent concept for any class -- an example is
Comparable or Cloneable.

In the end, interfaces are generally preferable for this kind of work;
but the reason is more an abstract design issue than a practical need to
avoid multiple inheritance.

This is all considerably short of Tony's "never use abstract classes,
ever", but I'm ignoring that because Tony's obviously having a bad week.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
A

Andrew McDonagh

Chris Smith wrote:

snipped..
Except, of course, that you'd never want your database access code or
XML parsing code to be aware of Swing.


snipped...

Absolutely, but coming up with a 'real world example' during the xmas
holidays is hard for me, as I don't (thank god) have access to my work
source code. Even if I did, it would be a very domain explicit example
which most people here wouldn't understand, as they wouldn't have worked
in that domain.

So this leaves this 'real world' example of why Sun have choosen this
particular idiom, albiet in a very simplified way.
 
R

Ryan Stewart

Andrew McDonagh said:
Absolutely, but coming up with a 'real world example' during the xmas
holidays is hard for me, as I don't (thank god) have access to my work
source code. Even if I did, it would be a very domain explicit example
which most people here wouldn't understand, as they wouldn't have worked
in that domain.

So this leaves this 'real world' example of why Sun have choosen this
particular idiom, albiet in a very simplified way.

I remain unconvinced. Interfaces and abstract classes are two different
animals intended for two different purposes. Maybe in your work, interfaces
predominant, but should java.lang.Number be an interface? What about
java.util.AbstractCollection, java.io_OutputStream, or java.text.DateFormat?
If your answer is yes, you are at the least promoting heavy-duty code
duplication.
 
C

Chris Smith

Andrew McDonagh said:
Absolutely, but coming up with a 'real world example' during the xmas
holidays is hard for me, as I don't (thank god) have access to my work
source code.

I think it's deeper than that. In fact, I don't think that a "real
world" example along the lines you're suggesting exists. Almost by
definition, it would introduce improper dependencies between modules.

Not that I disagree with using interfaces for this kind of thing. An
interface, in fact, is quite appropriate since it suggests something
different at an abstract level; that there is a way of interacting with
something that doesn't say anything about the implementation; versus an
abstract class, which suggests a partial implementation that can be
modified by overloading. So interfaces are great. Nevertheless, I
don't think the practical multiple inheritance problem really exists
with this kind of situation.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
C

Chris Smith

Andrew McDonagh said:
Sun, myself and others have no problem with adapter classes.

Sudsy was responding to Tony Morris, who said:

"It is arguable that abstract classes should be used at all
(inheritance from anything but an interface is pure evil, but
that's another story for another camp fire)."

That cause Ryan Stewart to ask why, and hence this subthread. Your
position obviously isn't as extreme as Tony's, so Sudsy's response
doesn't apply to you.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
C

Chris Smith

Chris Smith said:
something that doesn't say anything about the implementation; versus an
abstract class, which suggests a partial implementation that can be
modified by overloading.

Meant to say overriding. Sorry for the confusion.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top