Inheriting methods - what to put in super class.

Discussion in 'Java' started by Ook, Feb 21, 2007.

  1. Ook

    Ook Guest

    I have a class, Item. I have subclasses, CD, DVD, Book, etc (public
    class Book extends Item). In the subclass Book, for example, I have a
    method that returns the author of the book. I want to call this from a
    class outside of the Item class, and I do it like this:

    lcAuthor = item.author();

    In Book I have:

    public String author(){ return author; }

    In Item I have the same thing. Because the method exists in Book, the
    one in Item doesn't get called. This works fine. However, if I remove
    the method from Item, I get a compilation error because there is no
    item.author, even though there is a book.author.

    I can fix this by calling item.author like this:

    lcAuthor = ((Book) item).author();

    This also works. My question - which should I do? Should I leave the
    dummy call in my Item class that doesn't do anything? Is it better to
    cast item to Book? Or is there a better way to handle this?
     
    Ook, Feb 21, 2007
    #1
    1. Advertising

  2. Ook

    Lew Guest

    Ook wrote:
    > I have a class, Item. I have subclasses, CD, DVD, Book, etc (public
    > class Book extends Item). In the subclass Book, for example, I have a
    > method that returns the author of the book. I want to call this from a
    > class outside of the Item class, and I do it like this:
    >
    > lcAuthor = item.author();


    Many Java-aware tools and anything that uses JavaBeans follows a convention of
    naming such a method getAuthor(). This is not mandatory, but there are a lot
    of times when it's convenient to follow the convention.

    > In Book I have:
    >
    > public String author(){ return author; }
    >
    > In Item I have the same thing. Because the method exists in Book, the
    > one in Item doesn't get called. This works fine. However, if I remove
    > the method from Item, I get a compilation error because there is no
    > item.author, even though there is a book.author.
    >
    > I can fix this by calling item.author like this:
    >
    > lcAuthor = ((Book) item).author();
    >
    > This also works. My question - which should I do? Should I leave the
    > dummy call in my Item class that doesn't do anything? Is it better to
    > cast item to Book? Or is there a better way to handle this?


    Declare the "item" in this case to be of type Book, not Item.

    This is an analysis question, more than a programming one.

    When you declare a variable to be of type Item, you are essentially promising
    that all that variable needs is Item stuff. It is ignorant of any subtype
    behaviors or attributes.

    If your logic requires a Book at some point, you have essentially lied: you
    promised that your variable is only an Item, but here you "know" that it's
    "really" a Book! If it's a Book that you need, then make the variable of type
    Book in the first place.

    Then you do not need either the downcast or to implement non-Itemish stuff in
    Item.

    Inheritance in object orientation models something called an "is-a" relation.
    You have modeled your universe such that a Book /is-an/ Item. If you put
    "author()" in Item, then your universe is such that Items have authors. (That
    relationship is called "has-a".) If that is what you really mean, then put the
    author attribute in Item.

    OTOH, if it is not part of your universe that Items have authors, don't put
    author in Item. Give Items the attributes they have, and only the attributes
    they have.

    For discussion, let's take author out of Item, and ignore DVDs and the rest
    for a moment. Books have authors, publication dates, etc., and the Book class
    extends Item. Item does not have an author attribute.

    Now a Book /is-an/ Item, and additionally, it /has-a/ publication date, it
    /has-an/ author, etc.

    Back to your code.

    Here you are at a line that wants an author. That means the logic "knows" that
    you need things that have authors here. That means do not declare the variable
    to be of a type (Item) that does not have an author. Use a type that knows
    about having an author.

    - Lew
     
    Lew, Feb 22, 2007
    #2
    1. Advertising

  3. Ook

    Zootal Guest

    > When you declare a variable to be of type Item, you are essentially
    > promising that all that variable needs is Item stuff. It is ignorant of
    > any subtype behaviors or attributes.

    Then how do I go about accessing book/cd/dvd specific stuff? Right now I go
    through the Item, rather then directly accessing the book/cd/dvd class. All
    of my book, cd, and dvd objects are subclassed from my Item class - I create
    a "book" like this:

    Item book = new Book( author,...)

    And likewise for cds and dvds. My "library" is an ArrayList of Items. Each
    item could include book, cd, or dvd attributes

    I follow what you are saying, but only partially. Keep in mind that this is
    a school assigment, and the structure is basically what we were given to
    use. Our text also uses the same structure and similar methodology, which is
    why I used it.
     
    Zootal, Feb 22, 2007
    #3
  4. Ook

    Lew Guest

    Lew wrote:
    >> When you declare a variable to be of type Item, you are essentially
    >> promising that all that variable needs is Item stuff. It is ignorant of
    >> any subtype behaviors or attributes.


    Zootal wrote:
    > Then how do I go about accessing book/cd/dvd specific stuff? Right now I go
    > through the Item, rather then directly accessing the book/cd/dvd class. All
    > of my book, cd, and dvd objects are subclassed from my Item class - I create
    > a "book" like this:
    >
    > Item book = new Book( author,...)
    >
    > And likewise for cds and dvds. My "library" is an ArrayList of Items. Each
    > item could include book, cd, or dvd attributes
    >
    > I follow what you are saying, but only partially. Keep in mind that this is
    > a school assigment, and the structure is basically what we were given to
    > use. Our text also uses the same structure and similar methodology, which is
    > why I used it.


    Ah.

    It is common for academic examples to sacrifice some good ideas in order to
    focus on a particular topic.

    There are times when you need a looser collection like your List<Item> where
    you have to downcast, but it's always a compromise. In your situation I'd go
    with the downcast, but I cannot shake the conviction that there is a layer
    violation in the approach.

    I am guessing that you have a set of operations on each different Item, and
    that you are using the downcast type to determine what different operations to
    perform. I would rather see a method inside Item that does all the logic, and
    the override in each subtype that knows about things like authors.

    public interface Item
    {
    public void store( File out );
    }

    public class Book extends Item
    {
    private String author;
    public void store( File out )
    {
    PrintWriter wr = ... ( out ) ... ;
    wr.println( "author = "+ author );
    }
    }

    public class DVD extends Item
    {
    private String [] chapters;
    public void store( File out )
    {
    PrintWriter wr = ... ( out ) ... ;
    int i = 0;
    for( String chapter : chapters )
    {
    wr.println( "chapter ["+ ++i +"] = "+ chapter );
    }
    }
    }

    public class Main
    {
    public static void main( String [] args )
    {
    File f = ...;
    for ( Item item : list )
    {
    item.store( f );
    }
    }
    }

    Getters, setters, missing code and exception handling left as an exercise.

    - Lew
     
    Lew, Feb 22, 2007
    #4
    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. Guest

    super.super.super how?

    Guest, Feb 19, 2005, in forum: Java
    Replies:
    24
    Views:
    10,823
    Darryl Pierce
    Feb 24, 2005
  2. Fernando Rodriguez

    Getting the super class via the super() function

    Fernando Rodriguez, Nov 21, 2003, in forum: Python
    Replies:
    2
    Views:
    728
    Bob Willan
    Nov 22, 2003
  3. fi3nd
    Replies:
    0
    Views:
    389
    fi3nd
    Apr 8, 2010
  4. Hugh Sasse Staff Elec Eng

    Inheriting variables, super, and "not super"?

    Hugh Sasse Staff Elec Eng, Dec 9, 2003, in forum: Ruby
    Replies:
    7
    Views:
    132
    Hugh Sasse Staff Elec Eng
    Dec 11, 2003
  5. Matthew Braid

    $class::SUPER as well as $instance::SUPER?

    Matthew Braid, Aug 6, 2004, in forum: Perl Misc
    Replies:
    2
    Views:
    313
    Matthew Braid
    Aug 9, 2004
Loading...

Share This Page