Abtract Base Class Design problem

Discussion in 'Java' started by Bernd, Nov 10, 2003.

  1. Bernd

    Bernd Guest

    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
    Bernd, Nov 10, 2003
    #1
    1. Advertising

  2. Bernd

    xarax Guest

    "Bernd" <> wrote in message
    news:...
    > 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);
    }
    }
    xarax, Nov 10, 2003
    #2
    1. Advertising

  3. Bernd

    Chris Uppal Guest

    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
    Chris Uppal, Nov 10, 2003
    #3
  4. Bernd

    xarax Guest

    "Chris Uppal" <-THIS.org> wrote in message
    news:3faf71ef$0$106$...
    > 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!
    xarax, Nov 10, 2003
    #4
  5. Bernd

    Bernd Guest

    "Chris Uppal" <-THIS.org> wrote in message news:<3faf71ef$0$106$>...
    > 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, Nov 10, 2003
    #5
  6. Bernd

    Bernd Guest

    "xarax" <> wrote in message news:<EqFrb.5956$>...
    > "Bernd" <> 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
    Bernd, Nov 10, 2003
    #6
  7. Bernd wrote:

    > "Chris Uppal" <-THIS.org> wrote in message news:<3faf71ef$0$106$>...
    >
    >>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
    John C. Bollinger, Nov 10, 2003
    #7
  8. Bernd

    Chris Uppal Guest

    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, Nov 11, 2003
    #8
  9. Bernd

    Chris Uppal Guest

    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
    Chris Uppal, Nov 11, 2003
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. tomek
    Replies:
    2
    Views:
    664
    Andrey Tarasevich
    Dec 1, 2003
  2. Alf P. Steinbach
    Replies:
    6
    Views:
    530
    John Carson
    Sep 3, 2005
  3. Immortal Nephi

    Alternative to Abtract Class?

    Immortal Nephi, Apr 16, 2009, in forum: C++
    Replies:
    3
    Views:
    334
    Victor Bazarov
    Apr 17, 2009
  4. Hicham Mouline
    Replies:
    1
    Views:
    577
    Victor Bazarov
    Apr 20, 2009
  5. Karan Rajput
    Replies:
    2
    Views:
    128
    Abinoam Jr.
    Dec 22, 2010
Loading...

Share This Page