Another design for your critque - abstract method

Discussion in 'Java' started by Edward A Thompson, Jan 22, 2004.

  1. I have an abstract class with an abstract method. When I extend the
    class, 4 times out of 4I want to pass the method a String, but 1time
    out of 4 I want to pass it another class:

    So what I did was define someParam as an Object, and end up with the
    following:

    abstract class A {
    ....
    abstract calc (Object someParam) {};
    ....
    }

    public class A1 extends A {
    ...
    public calc (Object a) { String x = a.toString(); };
    ...
    }

    public class A4 extends A {
    ....
    public class calc (Object b) { MyClass m = (MyClass)b; };
    ....
    }

    Is this good/bad design? Is it standard? Is there a better way to
    accomplish this?

    Seems to me this allows something other than String or MyClass to be
    passed without the compiler's knowledge.

    I appreciate any feedback.
     
    Edward A Thompson, Jan 22, 2004
    #1
    1. Advertising

  2. Edward A Thompson

    Anton Spaans Guest

    You see this quite a bit (with, for example the equals() method).

    I would suggest to add one overloaded method to A4:

    public class A4 extends A {
    ....
    public class calc (Object b) { MyClass m = (MyClass)b; }; // or {
    calc((MyClass)b); }
    public class calc (MyClass b) { MyClass m = b; };
    ....
    }

    This will enable the compiler to bind calls to the method calc(MyClass) and
    no runtime class-cast is necessary.
    the method calc(Object) must still be there to satisfy the abstract
    baseclass.

    -- Anton.

    "Edward A Thompson" <> wrote in message
    news:...
    > I have an abstract class with an abstract method. When I extend the
    > class, 4 times out of 4I want to pass the method a String, but 1time
    > out of 4 I want to pass it another class:
    >
    > So what I did was define someParam as an Object, and end up with the
    > following:
    >
    > abstract class A {
    > ...
    > abstract calc (Object someParam) {};
    > ...
    > }
    >
    > public class A1 extends A {
    > ..
    > public calc (Object a) { String x = a.toString(); };
    > ..
    > }
    >
    > public class A4 extends A {
    > ...
    > public class calc (Object b) { MyClass m = (MyClass)b; };
    > ...
    > }
    >
    > Is this good/bad design? Is it standard? Is there a better way to
    > accomplish this?
    >
    > Seems to me this allows something other than String or MyClass to be
    > passed without the compiler's knowledge.
    >
    > I appreciate any feedback.
     
    Anton Spaans, Jan 22, 2004
    #2
    1. Advertising

  3. Anton Spaans sez:
    > "Edward A Thompson" <> wrote in message
    > news:...
    > You see this quite a bit (with, for example the equals() method).
    >
    > I would suggest to add one overloaded method to A4:
    >
    > public class A4 extends A {
    > ...
    > public class calc (Object b) { MyClass m = (MyClass)b; }; // or {
    > calc((MyClass)b); }
    > public class calc (MyClass b) { MyClass m = b; };
    > ...
    > }
    >
    > This will enable the compiler to bind calls to the method calc(MyClass) and
    > no runtime class-cast is necessary.
    > the method calc(Object) must still be there to satisfy the abstract
    > baseclass.


    >> ... 4 times out of 4 I want to pass the method a String

    ....
    >> public calc (Object a) { String x = a.toString(); };


    Are you sure you want to use Object.toString() here? If a is a String,
    you're making a copy. If it isn't, you'll still get a valid string but
    it probably won't be what you expect.

    I'd make it { String x = (String) a; } (actually, I'd use instanceof)
    and then, following Anton's logic, add another overloaded method to
    base class. One that takes String as parameter.

    And then I'd ask myself why have abstract method that takes an
    Object, and what's the point of having that abstract class at all.

    Dima
    --
    Surely there is a polite way to say FOAD. -- Shmuel Metz
    "Go forth and multiply". -- Paul Martin
     
    Dimitri Maziuk, Jan 22, 2004
    #3
  4. Dimitri Maziuk wrote:

    >>> public calc (Object a) { String x = a.toString(); };

    >
    > Are you sure you want to use Object.toString() here? If a is a String,
    > you're making a copy. If it isn't, you'll still get a valid string but
    > it probably won't be what you expect.


    Just a minor nitpick here:

    you're not making a copy if the variable a is a String.
    The toString() method in String is implemented like this:

    /**
    * This object (which is already a string!) is itself returned.
    *
    * @return the string itself.
    */
    public String toString() {
    return this;
    }

    --
    Kind regards,
    Christophe Vanfleteren
     
    Christophe Vanfleteren, Jan 23, 2004
    #4
  5. Edward A Thompson

    Ed Thompson Guest


    > And then I'd ask myself why have abstract method that takes an
    > Object, and what's the point of having that abstract class at all.


    Why have any abstract class? To force the subclass to implement a class
    of that name/type?
     
    Ed Thompson, Jan 23, 2004
    #5
  6. Edward A Thompson

    Adam Guest

    "Ed Thompson" <> wrote in message
    news:Ub%Pb.451$...
    >
    > > And then I'd ask myself why have abstract method that takes an
    > > Object, and what's the point of having that abstract class at all.

    >
    > Why have any abstract class? To force the subclass to implement a class
    > of that name/type?


    Yes, but your abstract class seems too abstract.
    Having
    abstract class MyClass
    {
    abstract void myMethod(Object o);
    }
    is considered to be bad design.

    Other people gave you a tip to use overloaded abstract methods:
    abstract class MyClass
    {
    abstract void myMethod(Type1 o);
    abstract void myMethod(Type2 o);
    abstract void myMethod(Type3 o);
    }
    and this is much better.
    But if your concrete classes just need *one*
    of those overloaded methods,
    you end up with something like:
    class MyConcreteClass extends MyClass
    {
    void myMethod(Type1 o)
    {
    System.out.println("Yes! MyConcreteClass expected Type1 as a
    parameter!");
    }
    void myMethod(Type2 o){ throw new Error("MyConcreteClass does not
    want or expect Type2!!!"); }
    void myMethod(Type3 o){ throw new Error("MyConcreteClass does not
    want or expect Type3!!!"); }
    }

    Which still is not perfect.

    Knowing that little about your problem I can't help much,
    but I think you could make some use of double dispatching
    (or Visitor pattern) in some form of it.

    Adam
     
    Adam, Jan 23, 2004
    #6
  7. "Anton Spaans" <aspaans at(noSPAM) smarttime dot(noSPAM) com> wrote in message news:<>...
    > ...
    > This will enable the compiler to bind calls to the method calc(MyClass) and
    > no runtime class-cast is necessary.
    > the method calc(Object) must still be there to satisfy the abstract
    > baseclass.
    > ...


    This is quite nice indeed. Excellent.


    Also, I'd add an instanceof check and throw IllegalArgumentException,
    but only if there is also some sort of 'supports()' call:

    abstract class Base {
    abstract void f(Object o) throws IllegalArgumentException;
    abstract boolean supports(Object o);
    }


    class Derived extends Base {
    void f(Object o) throws IllegalArgumentException{
    if (!(o instanceof String)){
    throw new IllegalArgumentException(...);
    }
    g((String) o);
    }

    void g(String s){
    ...;
    }

    boolean supports(Object o){
    return o instanceof String;
    }
    }


    The idea being that you should always be able to prevent
    exceptions if possible.

    -Hans
     
    Hans Granqvist, Jan 24, 2004
    #7
  8. > Also, I'd add an instanceof check and throw IllegalArgumentException,
    > but only if there is also some sort of 'supports()' call:
    >
    > abstract class Base {
    > abstract void f(Object o) throws IllegalArgumentException;
    > abstract boolean supports(Object o);
    > }
    >
    >
    > class Derived extends Base {
    > void f(Object o) throws IllegalArgumentException{
    > if (!(o instanceof String)){
    > throw new IllegalArgumentException(...);
    > }
    > g((String) o);
    > }
    >
    > void g(String s){
    > ...;
    > }
    >
    > boolean supports(Object o){
    > return o instanceof String;
    > }
    > }


    I don't see your use of supports here?
     
    Edward A Thompson, Jan 26, 2004
    #8
    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. DaKoadMunky
    Replies:
    4
    Views:
    572
    Lee Weiner
    Apr 20, 2004
  2. Sameer
    Replies:
    4
    Views:
    632
    Roedy Green
    Aug 31, 2005
  3. Replies:
    6
    Views:
    357
    dorayme
    Dec 12, 2006
  4. Chris Zopers

    Abstract method in non-abstract class

    Chris Zopers, Aug 8, 2008, in forum: ASP .Net
    Replies:
    2
    Views:
    399
    Göran Andersson
    Aug 8, 2008
  5. Stefan Ram
    Replies:
    27
    Views:
    794
    Stefan Ram
    Aug 17, 2009
Loading...

Share This Page