Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Java (http://www.velocityreviews.com/forums/f30-java.html)
-   -   Abtract Base Class Design problem (http://www.velocityreviews.com/forums/t128502-abtract-base-class-design-problem.html)

Bernd 11-10-2003 03:32 AM

Abtract Base Class Design problem
 
Hi,

I am having a problem to design

I got an abstract base class Base and
a couple of concrete subclasses, say
Child1 and Child2. With every class that is derived from
Base certain "cost" is associated
(a value, that despends only on the subclass, not on a
speific object of that class).
Now I would like to do the following:

1) Ask a subclass about its costs:
Child1.getCosts() // would return 10, because class Child1 costs 10
Child1.getCosts(); // would return 20, because class Child2 costs 20

2) ask a specific object about the costs of its subclass:
Child1 c1 = new Child1();
c1.getCosts() // would return 10, because class Child1 costs 10
Child1 c2 = new Child2();
c2.getCosts(); // would return 20, because class Child2 costs 20

3)ask a specific object about the costs of its subclass, but the reference
to the object is of class Base:
Base b;
b = new Child1();
b.getCosts() // would return 10, because class Child1 costs 10
b = new Child2();
b.getCosts(); // would return 20, because class Child2 costs 20

How do I design this?
(doesn't have to be a method getCosts(), could be via constants, etc)

I can't specify an abstract static method getCosts() in Base,
because Java does not allow that.
But if getCosts() is not static, I can't do Child1.getCosts().
If I leave it out of the base class, I always have to downcast every
Base object to its subclass, which I don't want, and there is
also no way to enforce the existence of a static getCosts function in
the subclasses.

I hope I made myself reasonable clear.

Please advice and thanks for you help.

Bernd

xarax 11-10-2003 05:33 AM

Re: Abtract Base Class Design problem
 
"Bernd" <bernd_no_junk@hotmail.com> wrote in message
news:231fe23.0311091932.5e52dfcb@posting.google.co m...
> Hi,
>
> I am having a problem to design
>
> I got an abstract base class Base and
> a couple of concrete subclasses, say
> Child1 and Child2. With every class that is derived from
> Base certain "cost" is associated
> (a value, that despends only on the subclass, not on a
> speific object of that class).
> Now I would like to do the following:
>
> 1) Ask a subclass about its costs:
> Child1.getCosts() // would return 10, because class Child1 costs 10
> Child1.getCosts(); // would return 20, because class Child2 costs 20


I assume you meant Child2, not Child1.

> 2) ask a specific object about the costs of its subclass:
> Child1 c1 = new Child1();
> c1.getCosts() // would return 10, because class Child1 costs 10
> Child1 c2 = new Child2();
> c2.getCosts(); // would return 20, because class Child2 costs 20
>
> 3)ask a specific object about the costs of its subclass, but the reference
> to the object is of class Base:
> Base b;
> b = new Child1();
> b.getCosts() // would return 10, because class Child1 costs 10
> b = new Child2();
> b.getCosts(); // would return 20, because class Child2 costs 20
>
> How do I design this?
> (doesn't have to be a method getCosts(), could be via constants, etc)
>
> I can't specify an abstract static method getCosts() in Base,
> because Java does not allow that.
> But if getCosts() is not static, I can't do Child1.getCosts().
> If I leave it out of the base class, I always have to downcast every
> Base object to its subclass, which I don't want, and there is
> also no way to enforce the existence of a static getCosts function in
> the subclasses.
>
> I hope I made myself reasonable clear.
>
> Please advice and thanks for you help.
>
> Bernd


public abstract class Base
{
protected final int cost;

public final int getCost()
{
return cost;
}

protected Base(final int theCost)
{
super();

cost = theCost;
}
}

public final class Child1
extends Base
{
private static final int COST = 10;

public static int COST()
{
return COST;
}

public Child1()
{
super(COST);
}
}

public final class Child2
extends Base
{
private static final int COST = 20;

public static int COST()
{
return COST;
}

public Child2()
{
super(COST);
}
}



Chris Uppal 11-10-2003 11:07 AM

Re: Abtract Base Class Design problem
 
xarax wrote:

> public abstract class Base
> [...]


Even simpler, if I've understood Bernd correctly, would be:

public abstract class Base
{
public abstract int getCost();
}

public class Child1()
{
public int getCost() { return 10; }
}

public class Child2()
{
public int getCost() { return 20; }
}

Why store a constant ?

-- chris




xarax 11-10-2003 01:46 PM

Re: Abtract Base Class Design problem
 
"Chris Uppal" <chris.uppal@metagnostic.REMOVE-THIS.org> wrote in message
news:3faf71ef$0$106$65c69314@mercury.nildram.net.. .
> xarax wrote:
>
> > public abstract class Base
> > [...]

>
> Even simpler, if I've understood Bernd correctly, would be:
>
> public abstract class Base
> {
> public abstract int getCost();
> }
>
> public class Child1()
> {
> public int getCost() { return 10; }
> }
>
> public class Child2()
> {
> public int getCost() { return 20; }
> }
>
> Why store a constant ?


The constant may come from a properties file
or other external medium during class initialization.
It is also better documentation. Finally, my example
is a "static final int", which means that a constant
is not stored at all. The compiler replaces the
field usage with the in-line constant.

2 cents worth...eek!



Bernd 11-10-2003 05:10 PM

Re: Abtract Base Class Design problem
 
"Chris Uppal" <chris.uppal@metagnostic.REMOVE-THIS.org> wrote in message news:<3faf71ef$0$106$65c69314@mercury.nildram.net> ...
> Even simpler, if I've understood Bernd correctly, would be:
>
> public abstract class Base
> {
> public abstract int getCost();
> }
>
> public class Child1()
> {
> public int getCost() { return 10; }
> }
>
> public class Child2()
> {
> public int getCost() { return 20; }
> }
>

No, that is unfortunately not possible,
because I cant' ask subclasses about their costs
(e.g. Child1.getCosts() does not work, because
getCosts() is not static).

Greetings

Bernd

Bernd 11-10-2003 05:42 PM

Re: Abtract Base Class Design problem
 
"xarax" <xarax@email.com> wrote in message news:<EqFrb.5956$nz.3885@newsread2.news.pas.earthl ink.net>...
> "Bernd" <bernd_no_junk@hotmail.com> wrote in message
> >
> > 1) Ask a subclass about its costs:
> > Child1.getCosts() // would return 10, because class Child1 costs 10
> > Child1.getCosts(); // would return 20, because class Child2 costs 20

>
> I assume you meant Child2, not Child1.


Yes, that was a typo.

> [helpful code snipped]


Thanks, I think that was what I was looking for.
Actually, i did something very similar after I posted
my question.

But I still see some problems:

1) I am wasting space.
Every object now allocates an int for "cost", instead of
using just one int per subclass. In my application this
won't be a problem, so I don't really care.

2) There are two different ways to ask about costs :
Base b = new Child1();
b.getCosts();

and

Child1.COST();

This is a bit counter-intuitive.

3) I don't enforce the existence of a static COST() function
in every subclass of Base (probably not possible in Java).
Well, OTOH I have to call the super
constructor with costs and if I use Child1.COST() and the method
does not exist, I get a compile-time error, so I don't know
whether this is really a big disadvantage.



Might be, that these issues can't be solved in Java in a more elegant fashion
and your solution is the optimal one. If someone has a better
idea, please post.


Bernd

John C. Bollinger 11-10-2003 10:00 PM

Re: Abtract Base Class Design problem
 
Bernd wrote:

> "Chris Uppal" <chris.uppal@metagnostic.REMOVE-THIS.org> wrote in message news:<3faf71ef$0$106$65c69314@mercury.nildram.net> ...
>
>>Even simpler, if I've understood Bernd correctly, would be:
>>
>>public abstract class Base
>>{
>> public abstract int getCost();
>>}
>>
>>public class Child1()
>>{
>> public int getCost() { return 10; }
>>}
>>
>>public class Child2()
>>{
>> public int getCost() { return 20; }
>>}
>>

>
> No, that is unfortunately not possible,
> because I cant' ask subclasses about their costs
> (e.g. Child1.getCosts() does not work, because
> getCosts() is not static).


You cannot have a static method and an instance method of the same class
with the same signature. Also, static methods are not polymorphic, so
there is no way to specify in a base class anything about static members
of a subclass. You could modify Chris' solution to accomodate, however:

public abstract class Base {
public abstract int getCost();
}

public class Child1() {
public int getCost() { return Child1.getCostStatic(); }
public static int getCostStatic() { return 10; }
}

public class Child2() {
public int getCost() { return Child2.getCostStatic(); }
public static int getCostStatic() { return 20; }
}


Call the static methods by whatever name you like, as long as the names
don't collide with those of the instance methods. Their presence and
names are only a convention you establish, however.


John Bollinger
jobollin@indiana.edu


Chris Uppal 11-11-2003 08:23 AM

Re: Abtract Base Class Design problem
 
Bernd wrote:

> No, that is unfortunately not possible,
> because I cant' ask subclasses about their costs
> (e.g. Child1.getCosts() does not work, because
> getCosts() is not static).


Right, I'd missed that in your list of requirements.

public abstract class Base
{
public abstract int getCost();
}

public class Child1()
{
public static final int INSTANCE_COST = 10;
public int getCost() { return INSTANCE_COST; }
}

public class Child2()
{
public static final int INSTANCE_COST = 20;
public int getCost() { return INSTANCE_COST; }
}

There is, of course, no particular magic that happens because the static fields
have the same name -- there is no semantic connection between them, but it
generally helps client programmers if there's some consistency.

Note that I've chosen to provide access to the constants as exposed fields, I
could have used static methods (as John Bollinger suggests), but I prefer this
way by a small margin. The main reason is that I feel that the difference
(method vs. field) does something to ameliorate the potential confusion in
programmers minds (those that have minds ;-) "which am I supposed to use ?"
since we are accustomed to seeing class constants exposed as static final
fields, and polymoprphically varying behaviour exposed as instance methods.

-- chris





Chris Uppal 11-11-2003 08:24 AM

Re: Abtract Base Class Design problem
 
xarax wrote:

> > Why store a constant ?

>
> The constant may come from a properties file
> or other external medium during class initialization.


No, I'd meant why store the constant in the abstract base class's
"instances" -- it commits the subclasses to an implementation strategy that may
be inappropriate (e.g. the value may be genuinely constant -- fixed at compile
time -- in which case there is no need to store it), and as a result places an
unwanted responsibility on them (to provide the value of the constant in the
constructor, which may be pointless).


> It is also better documentation.


I'd dispute that. If the constant in used in other contexts, then eliminating
the duplication by using a named constant is obviously a Good Thing. But the
context here is doesn't seem to be like that -- the method getCost() is *the*
"exposed constant" and as such *its* name is the one that provides the
documentation (or fails to). There's no documentary difference between

public final int SOME_USEFUL_NAME = 127;

and

public int someUsefulName() { return 127; }

provided, as I say, that the member in question is the sole "point of contact"
for the actual value, 127.


> Finally, my example
> is a "static final int", which means that a constant
> is not stored at all. The compiler replaces the
> field usage with the in-line constant.


Actually the static final int variable *is* still stored -- it's needed for
reflection, JNI, etc. You are right -- of course -- that references to it are
compiled away. (BTW did you realise that this applies to *all* final
int/etc/String fields that are initialised with a compile-time constant -- not
just to static ones ? I didn't up until a week or two ago. I haven't yet
thought of any use for it, but it's a moderately surprising bit of trivia...)

-- chris





All times are GMT. The time now is 07:41 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.