views:

319

answers:

7

Hi folks,

I have a little problem understanding the Java language

public class PhonebookEntryList extends List<PhonebookEntry>
{
    public PhonebookEntryList(String filename) throws IOException
    {
     //loadListFromFilename(filename);
    }

    public void saveListToFilename(String filename) throws IOException
    {
     //Do something to save it to a file
    }
}

I can't do this, because List is a generic Type (of course). I know what that means, but at the moment I can't think of a Solution for this problem.

Can you help me to solve it? Thanx!

+3  A: 

No, your only problem is that you're extending an interface; you must implement it instead.

public class PhonebookEntryList implements List<PhonebookEntry>

should work; or you might prefer to extend a concrete class:

public class PhonebookEntryList extends ArrayList<PhonebookEntry>

or

public class PhonebookEntryList extends LinkedList<PhonebookEntry>
Michael Myers
You're wrong, to; he have at least two problems with that code. I'd say three.
alamar
Really? Right offhand, I don't see anything else (assuming he simply omitted his actual code in the constructor and method).
Michael Myers
He shouldn't extend a List unless he want to modify its Listy behavior; it's a huge WTF to extend built-in collections to make your data POJOs.That's his main problem: his design is crap, I guess he also overrates OO as in "huge class hieracheries".
alamar
Saying he'll have a "problem" with the code isn't quite correct. The code could work just fine. It just will be incorrect from an design perspective. I just stumbled upon some legacy code that has this exact design error in it. It "works" just fine, even with my looking, pointing and screaming WTF at it.
Mike Cornell
Well, then you'll agree on the fact that such code is working is the third problem.
alamar
Yeah, I'm not saying I *like* this code. (If someone asked for instructions on how to jump off a cliff, would you answer? Sometimes I think I do.)
Michael Myers
This appears to be instructions for driving a coach party off a cliff. :)
Tom Hawtin - tackline
Not really. The code in this case extended a specific type of HashMap. It was named something else specific to the domain it was programmed in. It was only when i thought, hmmm, I wonder what Object xxxx looks like that I started swearing at it. When i get the chance I'll refactor it, but it's been working for several years and apparently working very well since the application's function is very highly regarded.
Mike Cornell
A: 

List<T> is an interface, not a class, so you can't inherit from it. You can, however, inherit from a generic type, supplying the type argument, if you wish to create, e.g. a collection for a specific type with some behaviour specific only to that type.

Rob
+3  A: 

You can't do that because List is an interface. But! You shouldn't extend or implement a List class to make a PhonebookEntryList, it's a design error.

You should do:

public class PhonebookEntryList
{
    private List<PhonebookEntry> entries;

    public PhonebookEntryList(String filename) throws IOException
    {
        //loadListFromFilename(filename);
    }

    public void saveListToFilename(String filename) throws IOException
    {
        //Do something to save it to a file
    }
}

I.e. your PhonebookEntryList should contain a list instead of inheriting it.

alamar
I'm not happy with that sollution, because I can't use the 'embedded list' from outside the class (Add, remove, find, ...)
classic is-a vs. has-a relationship.
Aaron F.
you can use the 'embedded list' from outside the class. Just add your own custom add(), remove(), find() methods to your phonebook. Then had those methods call your private List's corresponding add(), remove(), find() methods.
Aaron F.
Well, you should make it iterable or add a getList() method, but don't, please, don't extend built-in collections without *real* need!
alamar
Just to clarify why this is correct, you don't want to extend any type of List because you're not changing or adding any List-specific behavior. You're only *using* a List to store entries, so encapsulation should be preferred over inheritance.
Bill the Lizard
You should could also implement Iterable or List. If you add a getList() method, use Collections.unmodifableList().
GreenieMeanie
I much prefer Bill's response...Alamar, take note Bill manages to say the same thing with out telling the Question that he's an idiot.
Gareth Davis
I guess I wasn't in the right mood this evening :)
alamar
Fair enough, +1 for the now non grumpy alamar :-)
Gareth Davis
A: 

If you look at the JavaDoc for List, you'll see (as others mentioned) that it's an interface, not a class. What you most likely want to do is look on the same JavaDoc page at "All Known Implementing Classes" and you'll see AbstractList. Extend this. Alternatively, extend one of the non-abstract List implementations.

Note: Most of the time when someone starts to extend one of the Java Collection classes, you're going down the wrong route. Usually, it's better to use one of the existing collections in your class and proxy any collections-style requests that you need. Or return an unmodifiable proxy of your collection:

public class MyClass {
  private final List<PhonebookEntry> myList = new LinkedList<PhonebookEntry>();

  public List<PhonebookEntry> getList() {
    return Collections.unmodifiableList(myList);
  }
}

Usually, it's best to extend a class only if you intend to have different behavior than the class you are extending. Inheritance is more brittle than composition.

Eddie
Please, don't export iterators; it doesn't play well with Java 5 and its 'smart for'.
alamar
And you don't want to make it implement Iterable, for the same reason you don't want it to implement List.Better make itpublic List<PhonebookEntry> entries() { return Collections.unmodifiableList(entries); }
alamar
Fair points, both. I updated my code sample.
Eddie
A: 

List<T> is an interface.

If you want to extend a class you'll have to choose an implementation (ArrayList<T> maybe): extends ArrayList<PhonebookEntry>

If you want to implement a List change your code to: implements List<PhonebookEntry>

bruno conde
Can the person who down voted me explain why?
bruno conde
Someone's apparently very angry.
Mike Cornell
A: 

Your Problem is that you are trying to extend an interface rather than implement it.

Composition is what you want. Create a class that wrapps a List (or something that iplements that interface)

and add functionality.

Omar Kooheji
A: 

Should I mention that List is an Interface and not a Class? Nah. I think you got the point by now.

I would like to point out, however, that it's usually better NOT to embed the persistence mechanism within the list class. There's this thing called the Visitor pattern that works better. By placing the actual persistency code in a seperate class, the overall logical complexity of the app gets reduced (at the expense of an extra class), and your phonebook becomes liberated to be used in places where having dependencies on the persistency mechanism that looked good when you first designed the code don't look so good anymore. For example, if you wanted to make the Phonebook be an item in an ORM-referenced database.

Tim H
Guess what? He doesn't need this class if he splits the persistense stuff!
alamar