CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 24
  1. #1
    Join Date
    Jun 2009
    Posts
    2

    Polymorphism & Generics

    Hi,

    I have this issue that is replicated in my code and I have been thinking of in recent weeks.

    An example:

    Code:
    public class Parent
    {    public String hi()
        {
            return "Hi, I'm Parent";
        }
    }
    
    public class Child1 extends Parent
    {
        public String hi()
        {
            return "Hi, I'm Child1";
        }
    }
    
    public class Child2 extends Parent
    {
        public String hi()
        {
            return "Hi, I'm Child2";
        }
    }
    
    public class Doubt
    {
        public void saluteAll( List<Parent> list)
        {
            for( Parent p : list ) {
                salute(p);
                salute(p);
            }
        }
    
        private void salute( Parent i )
        {
            System.out.println("parent says: " + i.hi());
        }
    
        private void salute( Child1 i )
        {
            System.out.println("child1 says: " + i.hi());
        }
    
        private void salute( Child2 i )
        {
            System.out.println("child2 says: " + i.hi());
        }
    }
    The salute calls at the saluteAll() method print

    Code:
    parent says: Hi, I'm Child1
    parent says: Hi, I'm Child2
    What would I need to do in order to print the following?

    Code:
    child1 says: Hi, I'm Child1
    child2 says: Hi, I'm Child2
    In my code, I have a collection of ChildX objects that I need to treat as a collection but since functionality on most of them can't be abstracted via polymorphism, that is, general methods common to all ChildX (some are but not all) can't be defined (and the lower the hierarcy, the more particular each class is), I have to do something like this:

    Code:
    public void saluteAll( List<Parent> list )
    {
        for( Parent p : list ) {
            if( p instanceof Child1 ) {
    
                salute( (Child1) p );
    
            } else if( p instanceof Child2 ) {
    
                salute( (Child2) p );
    
            }
        }
    }
    In my opinion, this is ugly. I'm aware that I may be at this scenario due to a poor OO design, so please enlighten me! I'd really appreciate it.

    Thanks in advance

  2. #2
    Join Date
    May 2009
    Posts
    2,413

    Re: Polymorphism & Generics

    Quote Originally Posted by ivotron View Post
    In my opinion, this is ugly. I'm aware that I may be at this scenario due to a poor OO design, so please enlighten me! I'd really appreciate it.
    As you indicate it's better to have a fully polymorphic design. But if this is not the case you can use the Visitor design pattern. One can say the Visitor pattern is the OO way of making a downcast without actually making it.

    You start by defining a Visitor interface like this,

    Code:
    public interface Visitor {
       void salute(Child1 i);
       void salute(Child2 i);
    }
    Then you add an accept method in Parent which takes a Visitor object as parameter, like
    Code:
    public abstract Parent {
       public abstract void accept(Visitor v);
    }
    Now each Child subclass must implement the accept method,
    Code:
    public class Child1 extends Parent {
       public void accept(Visitor v) { //  exactly the same in all Child subclasses
          v.salute(this); //  the salute method with the Child1 parameter gets called thanks to overloading
       }
    }
    Now you must implement a concrete Visitor, say ChildVisitor,
    Code:
    public class ChildVisitor implements Visitor {
        public void salute(Child1 i) {
            System.out.println("child1 says: " + i.hi());
        }
        public void salute(Child2 i) {
            System.out.println("child2 says: " + i.hi());
        }
    }
    Finally you use the concrete Visitor object like this,
    Code:
    public void saluteAll( List<Parent> list)  {
       Visitor v = new ChildVisitor(); // concrete Visitor
       for( Parent p : list ) {
          p.accept(v); // the Visitor is passed to each Child which calls the correct salute method
        }
    }
    That's the Visitor pattern. It's not very intuitive but in principle it allows each Child subclass to reveal its own type (by calling the correct salute method in its accept method). This removes the need for having to figure out the Child's type (using instanceof) and downcast.

    The Visitor pattern is based on a so called double dispatch. It's called so because given a Parent object two polymorphic selections are made at runtime to call the proper salute method. First,

    p.accept(v);

    where the accept method is polymorphically selected, and then,

    v.salute(this);

    where the salute method is polymorphically selected.
    Last edited by nuzzle; June 24th, 2009 at 07:25 AM.

  3. #3
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Polymorphism & Generics

    nuzzle's suggestion of using the Visitor pattern is a very nice solution, and it's worth spending a little time to understand just how it works.

    A big advantage of Visitor is that it makes it easy to add new operations to your hierarchy, and it's all in one place, but there are a couple of disadvantages - it makes more work to add new items to the hierarchy, and it may be confusing for novice coders maintaining code. Like most of these things, it's worth trying it out to see if it fits your needs, but don't go overboard with it - overuse of the Visitor pattern becomes 'Tourism' ;-)

    An alternative would be to take another look at your overall design - you say that functionality on most of them can't be abstracted via polymorphism, but this suggests that these classes aren't really related in the way you're trying to use them. Sometimes you can avoid this cross-cutting polymorphism problem by keeping multiple lists of the objects according to their different roles. For example, you have a Parent list of Child objects for when you need to call Parent hierarchy methods common to all Child objects, a TypeA list of Child objects for all Child objects that have a TypeA interface, a TypeB list of Child objects for all Child objects that have a TypeB interface, and so-on. Of course, this means breaking your code up into modules that each deal with a particular interface type, so instead of doing all necessary processing in a single loop, you have separate loops for processing each type, which means objects will get processed more than once, but as different types. It also means you need to be careful when adding and removing objects that they are added or removed from all the relevant lists, but that's not too difficult.

    For example, a college has a variety of people ('members') associated with it in different roles. There are Students, and Staff, including Tutors, Caretakers, etc. We sometimes want to handle them all as CollegeMembers, and sometimes by their individual roles. We can keep track of who has which role in separate role-based lists:
    Code:
    interface CollegeMember {}
    interface Staff extends CollegeMember {}
    interface Student extends CollegeMember {}
    interface Tutor extends Staff {}
    interface Caretaker extends Staff {}
    
    Student addStudent(...) {
        Student student = new Student(...);
        collegeMemberList.add(student);
        studentList.add(student);
        return student;
    }
    
    Tutor addTutor(...) {
        Tutor tutor = new Tutor(...);
        collegeMemberList.add(tutor);
        staffList.add(tutor);
        tutorList.add(tutor);
        return tutor;
    }
    
    Caretaker addCaretaker(...) {
        Caretaker caretaker = new Caretaker(...);
        collegeMemberList.add(caretaker);
        staffList.add(caretaker);
        dogsbodyList.add(caretaker);
        return caretaker;
    }
    
    void processSalaries(List<Staff> staffList) { ... }
    void sendNewTermNotifications(List<CollegeMembers> memberList) { ... }
    void processExamResults(List<Students> studentlist) { ... }
    etc.
    Not a very clever example, but you get the idea. This can be a lot easier to manage when a database is used to store the objects.

    Always do the hard part first. If the hard part is impossible, why waste time on the easy part? Once the hard part is done, you're home free.
    Always do the easy part first. What you think at first is the easy part often turns out to be the hard part. Once the easy part is done, you can concentrate all your efforts on the hard part...

    A. Schapira
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  4. #4
    Join Date
    May 2009
    Posts
    2,413

    Re: Polymorphism & Generics

    Quote Originally Posted by dlorde View Post
    and it may be confusing for novice coders maintaining code.
    This is the argument I won't accept.

    As a programmer one should always do one's best and today that involves knowing and using the standard OO design patterns, including Visitor. It's professional and standard procedure. Morons will never understand your code anyway.

  5. #5
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Polymorphism & Generics

    Quote Originally Posted by nuzzle View Post
    This is the argument I won't accept.
    You don't have to accept it if you run your own company and do your own recruitment.

    As a programmer one should always do one's best and today that involves knowing and using the standard OO design patterns, including Visitor. It's professional and standard procedure.
    The reality is there are plenty of coders working out there who don't (yet) know the Visitor pattern, or are not familiar enough with it to easily recognise it or be comfortable working with it. My point is that in a business environment you need to take account of the likely level of knowledge of the coders who will maintain the code when choosing your idioms.

    Morons will never understand your code anyway.
    Is that your way of saying that any programmer who doesn't know the Visitor pattern is a moron?

    Programs must be written for people to read, and only incidentally for machines to execute...
    H. Abelson and G. Sussman
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  6. #6
    Join Date
    May 2009
    Posts
    2,413

    Re: Polymorphism & Generics

    Quote Originally Posted by dlorde View Post
    Is that your way of saying that any programmer who doesn't know the Visitor pattern is a moron?
    Yes. Do you think otherwise?

  7. #7
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Polymorphism & Generics

    Quote Originally Posted by nuzzle View Post
    Yes. Do you think otherwise?
    Yes.

    They know enough who know how to learn...
    J. Adams
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  8. #8
    Join Date
    May 2009
    Posts
    2,413

    Re: Polymorphism & Generics

    Quote Originally Posted by dlorde View Post
    Yes.
    Fine.
    Last edited by nuzzle; June 26th, 2009 at 08:28 PM.

  9. #9
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Polymorphism & Generics

    Quote Originally Posted by nuzzle View Post
    Fine.
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  10. #10
    Join Date
    Jun 2009
    Posts
    2

    Re: Polymorphism & Generics

    Interesting replies guys, I'll considered them when I get to the refactoring phase. Thanks a lot !

  11. #11
    Join Date
    May 2009
    Posts
    2,413

    Re: Polymorphism & Generics

    Quote Originally Posted by dlorde View Post
    The reality is there are plenty of coders working out there who don't (yet) know the Visitor pattern, or are not familiar enough with it to easily recognise it or be comfortable working with it. My point is that in a business environment you need to take account of the likely level of knowledge of the coders who will maintain the code when choosing your idioms.
    The original Design Patterns have been around for 15 years now as examples of good OO design. They're well established and tought in school education and company training. The Design Patterns constitute a language of program design understood by most. I can see no reason why not using them freely in a new OO design today. Especially in Java, a language devoted to OO.

    In fact one problem with your solution is that you don't relate it to the Design Patterns. If you did it would be much easier to understand what you're talking about. So do yourself a favour. Don't be a moron - start using the Design Patterns! You'll benefit from it.
    Last edited by nuzzle; July 7th, 2009 at 05:16 PM.

  12. #12
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Polymorphism & Generics

    Quote Originally Posted by nuzzle View Post
    The original Design Patterns have been around for 15 years now as examples of good OO design. They're well established and tought in school education and company training. The Design Patterns constitute a language of program design understood by most. I can see no reason why not using them freely in a new OO design today. Especially in Java, a language devoted to OO.
    I agree - although in my experience most novice programmers don't know much about DPs unless they've been on a decent programming course or certification.

    In fact one problem with your solution is that you don't relate it to the Design Patterns.
    You're probably right, but it's the idiom or technique that counts.

    If you did it would be much easier to understand what you're talking about.
    Perhaps, although I find most people can cope just as well with a simple explanation and an example.

    So do yourself a favour. Don't be a moron - start using the Design Patterns! You'll benefit from it.
    Thanks for the advice - as it happens I've been using DPs since the late '90s, from Alexander's Pattern Languages and the 'Gang Of Four', to the more recent and amusing 'Head First DPs' and others. It's all good stuff.

    Being abstract is something profoundly different from being vague... The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise...
    E. Dijkstra
    Last edited by dlorde; July 8th, 2009 at 05:51 AM.
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  13. #13
    Join Date
    May 2006
    Location
    UK
    Posts
    4,473

    Re: Polymorphism & Generics

    Quote Originally Posted by nuzzle
    Don't be a moron - start using the Design Patterns
    Resorting to insults rarely strenghens one's agrument. In fact it's probably the verbal equivalent of coding using anti-patterns ie it's counter-productive.

  14. #14
    Join Date
    Feb 2008
    Posts
    966

    Re: Polymorphism & Generics

    Quote Originally Posted by nuzzle View Post
    They're well established and tought in school education and company training. The Design Patterns constitute a language of program design understood by most. I can see no reason why not using them freely in a new OO design today. Especially in Java, a language devoted to OO.
    Ironically you misspelled "taught" while referencing higher education

    You are making huge assumptions about schooling and company training. Perhaps where you received your education they covered the Visitor pattern. The school that I went to did cover design patterns, but Visitor was not one of them. Calling somebody a moron because they have never seen the Visitor pattern is just plain lame. Am I expected to know every single design pattern out there? How many should they have covered in school? Why should they have taught me the Visitor pattern over the ones they did cover?

    If you work for a company that sends you to training for design patterns, or holds in house training, then it sounds like you work for a great place. Mine, like most out there, expect us to train ourselves for the most part (occasionally sending us to conferences or training, but never on something specific as design patterns).

  15. #15
    Join Date
    Apr 2007
    Posts
    425

    Re: Polymorphism & Generics

    Quote Originally Posted by nuzzle View Post
    I can see no reason why not using them freely in a new OO design today.
    Quote Originally Posted by ProgramThis View Post
    Ironically you misspelled "taught" while referencing higher education
    Say that over and over (top quote), and try to make sense of that sentence fragment. Where I went to school, we also studied technical English. Being able to communicate clearly will go a long way, longer perhaps than arguing whether a (what I expect is a) novice-intermediate developer should implement a design pattern in his solution.

    Quote Originally Posted by nuzzle View Post
    It's professional and standard procedure.
    It may be standard procedure for your organization, (and I am very skeptical that you have a documented coding standard so thorough that it advocates the use of design patterns wherever possible, let alone that such a document is or can practically be enforced), but that's about it.

    Quote Originally Posted by nuzzle View Post
    Morons will never understand your code anyway
    This is irrelevant. What you need to understand is that this is a forum that people are offering advice. The vast majority of people on these forums asking the questions are not employed, are students, are learning, and are studying.

    The bottom line is that the OP is still evidently learning, and has probably not visited this thread since your original response.

    Stop tossing insults around. We get it, everyone's a bad *** punk when they have an online persona to hide behind.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured