Java supports multiple inheritance, sometimes



  • We all know that Java doesn't support multiple inheritance. This means that you can not do the following:

    class base1 {}
    class base2 {}
    class sub extends base1, base2 {}

    However, the following is valid, compiles and can be used at-will (I'm using 1.5.x):

    interface base1 {}
    interface base2 {}
    interface sub extends base1, base2 {}
    

    So, multiple inheritance of classes is not allowed, but you can multiply inherit interfaces? These folks were bright enough to design a new language, complete with VM, but couldn't be consistent with the implementation of the two main features of the language? WTF?



  • @codeman said:

    We all know that Java doesn't support multiple inheritance. This means that you can not do the following:

    class base1 {}
    class base2 {}
    class sub extends base1, base2 {}

    However, the following is valid, compiles and can be used at-will (I'm using 1.5.x):

    interface base1 {}
    interface base2 {}
    interface sub extends base1, base2 {}
    

    So, multiple inheritance of classes is not allowed, but you can multiply inherit interfaces? These folks were bright enough to design a new language, complete with VM, but couldn't be consistent with the implementation of the two main features of the language? WTF?



    There is nothing wrong with multiple interface inheritance. If a class can implement multible interfaces, why should an interface not be allowed to inherit from multiple interfaces?


  • @codeman said:

    However, the following is valid, compiles and can be used at-will (I'm using 1.5.x):
    interface base1 {}
    interface base2 {}
    interface sub extends base1, base2 {}
    

    So, multiple inheritance of classes is not allowed, but you can multiply inherit interfaces? These folks were bright enough to design a new language, complete with VM, but couldn't be consistent with the implementation of the two main features of the language? WTF?



    Erm. Yes. It works that way on purpose. Interfaces are quite different from multiple inheritance, and are the "proper" way to do it.

    When you have two superclasses, and both implement a method with the same signature, which one is the VM supposed to call?

    Is <font face="Courier New">((base1)sub).toString()</font> going to return a different result as <font face="Courier New">((base2)sub).toString()</font>? Can you see the madness that multiple inheritance creates?

    By the way, you don't even need the 'sub' interface. You can just write
        <font face="Courier New">class foo implements base1, base2 {}</font>

    Both interfaces can declare a toString() method, but it's only going to be IMPLEMENTED once. Interfaces also cannot declare fields;

    suppose you have
    <font face="Courier New">class base1 {
        public int myValue = 1;
    }
    class base2 {
        public int myValue = 2;
    }
    class sub extends base1, base2 {
      public String toString() {
           return "My value is " + myValue;
      }
    }</font>

    What do you expect the function to print? 1? 2? WHY?! It makes no sense.

    Interfaces are DESIGNED to avoid the problems that multiple inheritance causes, while still retaining ALL of their usefulness.



  • Methinks you missed my point.

    Yes, classes can implement multiple interfaces, no classes can not extend multiple classes, and Nandurius' example was alluding to C++ style virtual inheritance.

    I was not attempting to debate the implementation of implementing multiple interfaces. The point was that Java claims to not permit multiple inheritance, yet allows you to define an interface that extends multiple interfaces, which is, by definition, multiple inheritance.



  • @codeman said:

    I was not attempting to debate the implementation of implementing multiple interfaces. The point was that Java claims to not permit multiple inheritance, yet allows you to define an interface that extends multiple interfaces, which is, by definition, multiple inheritance.


    So wait, your whole point is that you can write
    "<font face="Courier New">interface blah extends interface1, interface</font>2"
     rather than
    "<font face="Courier New">interface blah implements interface1, interface2</font>"?

    Just think about that, for a minute. An interface doesn't implement any functionality. It just defines it. Writing extends here makes perfect sense. And it has nothing to do with C++ multiple inheritance (as pointed out above) other than sharing the same keyword.

    @codeman said:
    The point was that Java claims to
    not permit multiple inheritance


    For CLASSESS. Happy now?! Where is the WTF? Is it with your own, over simplified claim/definition?



  • the real WTF here is that codeman seems to think he's smarter than all the people over at Sun when he really doesn't understand the deference between a parent class and an implemented interface.  



  • @tster said:

    the real WTF here is that codeman seems to think he's smarter than all the people over at Sun when he really doesn't understand the deference between a parent class and an implemented interface.  

    Or perhaps you aren't smart enough to get the difference between a comment on SYNTAX, as opposed to implemented functionality ;)

     



  • @Nandurius said:


    Erm. Yes. It works that way on purpose. Interfaces are quite different from multiple inheritance, and are the "proper" way to do it.

    I have to disagree with that one. Imho, interfaces are really a cheap hack for abstract classes combined with proper multiple inheritance (a la Eiffel, where you can rename inherited members).



  • @Nandurius said:



    -snip-

     Interfaces also cannot declare fields;

    suppose you have
    <font face="Courier New">class base1 {
        public int myValue = 1;
    }
    class base2 {
        public int myValue = 2;
    }
    class sub extends base1, base2 {
      public String toString() {
           return "My value is " + myValue;
      }
    }</font>

    What do you expect the function to print? 1? 2? WHY?! It makes no sense.

    Interfaces are DESIGNED to avoid the problems that multiple inheritance causes, while still retaining ALL of their usefulness.



    Actually, Interfaces can declare and define fields. We do this all the time to declare our constants. However, the following code example will result in a compiler error:

    <font face="Courier New">interface base1 {
        public int myValue = 1;
    }
    interface  base2 {
        public int myValue = 2;
    }
    class sub implements base1, base2 {
      public String toString() {
           return "My value is " + myValue;
      }
    }</font>

    I had to test it myself... I guess, we spend our whole life learning :)



  • @Nandurius said:

    When you have two superclasses, and both implement a method with the same signature, which one is the VM supposed to call?

    Some solutions:
    1) Define an order.  For example, give precedence to those classes that appear first in the list of extended classes.
    2) Force an override on the subclass.
    3) Allow subclasses to rename base class members.

    @Nandurius said:
    Is <font face="Courier New">((base1)sub).toString()</font> going to return a different result as <font face="Courier New">((base2)sub).toString()</font>?

    No, never.  They must both use the same vtable for that call.  For non-virtual methods, you probably want distinct behavior depending on the referenced type.  C# has a kind of support for this with the 'new' method keyword.

    @Nandurius said:
    Can you see the madness that multiple inheritance creates?

    Not really.  I think MI is an extremely useful tool, and it's a shame that even non-conflicting base classes may not be aggregated into a single subclass in popular languages like Java and C#.  But as I've stated above, there's still logical solutions for when conflicts occur.

    @Nandurius said:
    Interfaces are DESIGNED to avoid the problems that multiple inheritance causes, while still retaining ALL of their usefulness.

    Interfaces are extremely limited; they do not retain all of the usefulness of MI.



  • @RiX0R said:

    @Nandurius said:


    Erm. Yes. It works that way on purpose. Interfaces are quite different from multiple inheritance, and are the "proper" way to do it.

    I have to disagree with that one. Imho, interfaces are really a cheap hack for abstract classes combined with proper multiple inheritance (a la Eiffel, where you can rename inherited members).



    True, that really is a matter of opinion. I only used "proper" to mean making the C++ approach workable without conflicts and WTF's.

    I read the Eiffel paper, and I a bit disappointed. It's certainly a fair enough solution to naming collisions (as far as making the code at least predictable) but I'm not convinced that it's clean and even needed.

    Coming from a Java background, I haven't run into any situations yet where I would've wanted to have multiple inheritance. I think I only wanted to do that once when I was still learning Java, and was taking a naive approach to the design and structure of the program. Of course, it ended up working fine without any need for multiple inheritance at all.
    My thought is that those who are used to C++ use it, effectively, and structure their programs in ways to take advantage of it. Those used to Java use interfaces instead, structure the programs to take advantage of interfaces, and that works just as well.



  • Ok, totally off topic, but I'm looking at the Eiffel website, and I can't figure out what the hell it's supposed to be.

    From looking at the website, it seems to be a pascal ripoff with a lot of marketing bullshit thrown in.

    "What is Eiffel?

    Actually, in this case it is short for "The Eiffel Development FrameworkTM" - a comprehensive approach to software development. It consists of the Eiffel methodology for the beginning-to-end construction of robust, reusable software; the Eiffel language, which supports the methodology; and EiffelStudioTM, the environment that contains the Eiffel compiler and the complete set of productivity tools which make the development environment. The individual parts fit together with and support each other's function in the pursuit of making the best software possible.

    No other software development system has been designed to work in such a simple and powerful way.

    The results of this approach and design are staggering. Productivity increases. Cost of ownership goes down. Quality levels go up."


    I'm sorry, that left me feeling quite sick. Please tell me if I'm wrong, but I'm throwing this in the same bag as the "awesome" MUMPS language posted a while ago.

    Maybe there's a _real_ FAQ targeted towards developers and not buzzword-hungry managers somewherE?


  • @codeman said:

    We all know that Java doesn't support multiple inheritance. This means that you can not do the following:

    class base1 {}
    class base2 {}
    class sub extends base1, base2 {}

    However, the following is valid, compiles and can be used at-will (I'm using 1.5.x):

    interface base1 {}
    interface base2 {}
    interface sub extends base1, base2 {}
    

    So, multiple inheritance of classes is not allowed, but you can multiply inherit interfaces? These folks were bright enough to design a new language, complete with VM, but couldn't be consistent with the implementation of the two main features of the language? WTF?

    The issue that the Java devs didn't want to tackle with multiple inheritance is the MRO (Method Resolution Order), especially when you get a diamond inheritance graph. Interfaces don't specify implementation, interface inheritance is therefore more or an aggregation than an inheritance and doesn't have multiple inheritance-related issues.

    @Nandurius said:
    Erm. Yes. It works that way on purpose. Interfaces are quite different from multiple inheritance, and are the "proper" way to do it.

    They're the proper nothing, interfaces are merely the way to avoid multiple inheritance in statically explicitely typed languages, they're only the "proper" way to do things as far as Java is concerned.

    @Nandurius said:
    Interfaces are DESIGNED to avoid the problems that multiple inheritance causes, while still retaining ALL of their usefulness.

    No, they're designed to implement the polymorphic behaviours of MI in statically explicitely typed languages, and they lose a lot of MI's usefullness, if they didn't they'd have the same issues.

    Interfaces are merely purely abstract classes (absract classes with only abstract methods) in a multiple-inheritance context, and they're implemented that way in Java under the hood (check the error message you get when you don't implement a method specified in an interface versus the one you get when you don't override an abstract method)

    @Nandurius said:
    Ok, totally off topic, but I'm looking at the Eiffel website, and I can't figure out what the hell it's supposed to be.

    From looking at the website, it seems to be a pascal ripoff with a lot of marketing bullshit thrown in.

    "What is Eiffel?

    Actually, in this case it is short for "The Eiffel Development FrameworkTM" - a comprehensive approach to software development. It consists of the Eiffel methodology for the beginning-to-end construction of robust, reusable software; the Eiffel language, which supports the methodology; and EiffelStudioTM, the environment that contains the Eiffel compiler and the complete set of productivity tools which make the development environment. The individual parts fit together with and support each other's function in the pursuit of making the best software possible.

    No other software development system has been designed to work in such a simple and powerful way.

    The results of this approach and design are staggering. Productivity increases. Cost of ownership goes down. Quality levels go up."


    I'm sorry, that left me feeling quite sick. Please tell me if I'm wrong, but I'm throwing this in the same bag as the "awesome" MUMPS language posted a while ago.

    Maybe there's a _real_ FAQ targeted towards developers and not buzzword-hungry managers somewherE?

    It's a fully OO language (with an unified type system: everything is an object period) strongly based on Design by Contract (implemented at the language level).

    It's syntax is fairly close to ALGOL's or Pascal's indeed.

    Looks like a quite nice language, but I haven't had the time to really research it yet. If you want more informations on it you may be interrested in the NICE page, in SmartEiffel's website (a GNU Eiffel compiler) or in Eiffel Software's Wiki (seems less buzzword-laden that the main website). You can also find an invitation to eiffel and an eiffel tutorial on EiffelSoftware's website.



  • @Nandurius said:

    Maybe there's a real FAQ targeted towards developers and not buzzword-hungry managers somewherE?


    I'm not sure about a FAQ, but the book Object-Oriented Software Construction uses Eiffel. It's meant to teach OOP at the same time (with Eiffel just as notation) - the author (the designer of Eiffel) argues for each feature of the language as he adds it, trying to show that the language needs it and it's better than the other ways of doing it, and trying to think of problems with it. I think it's a good book, myself.

    As far as the language goes, Eiffel is a fairly simple OO language. It's pure - things like integers are just objects that live on the stack, and there's syntax to declare a type as living on the stack. You can declare preconditions, postconditions and invariants and have them automatically checked. It supports multiple inheritance and has a scheme to get it to work quite well. It has generic types, and the type system seems to be quite sound.



  • I'm sorry but there is no WTF here. One of the main reasons interfaces exist is to give what is effectively multiple inheritance. What you have 'stumbled' upon is actually the bloody point!

    Classes are NOT interfaces and vica versa so why on earth should the be "consistent". Taht's like saying "you can multiply int but not booleans .... WTF, that's not consistent"

    The WTF is that this WTF is not in fact a WTF!



  • @Twisted said:


    Actually,
    Interfaces can declare and define fields. We do this all the time to
    declare our constants. However, the following code example will result
    in a compiler error:

    <font face="Courier New">interface base1 {
        public int myValue = 1;
    }
    interface  base2 {
        public int myValue = 2;
    }
    class sub implements base1, base2 {
      public String toString() {
           return "My value is " + myValue;
      }
    }</font>




    But the following will compile and work just fine:



    <font face="Courier New">interface base1 {
        public int myValue = 1;
    }
    interface  base2 {
        public int myValue = 2;
    }
    class sub implements base1, base2 {
      public String toString() {
           return "My value is " + base1.myValue;
      }
    }

    <font face="Times New Roman">

    I agree, no WTF. It's a well-designed feature of the language that has been there since the beginning.</font>

    </font>



  • @voyager said:

    Classes are NOT interfaces and vica versa

    Guess what? Java disagrees.

    interface TestInterface {
        void foo();
    }
    

    public class InterfaceTestClass implements TestInterface {
    public void bar() {
    System.out.println("bar");
    }
    }

    public abstract class AbstractTestClass {
    abstract void foo();
    }

    public class InheritanceTestClass extends AbstractTestClass {
    public void bar() {
    System.out.println("bar");
    }
    }

    javac's output:

    C:\Documents and Settings\xmorel\Bureau>javac TestInterface.java
    

    C:\Documents and Settings\xmorel\Bureau>javac -cp . InterfaceTestClass.java
    InterfaceTestClass.java:1: InterfaceTestClass is not abstract and does not overr
    ide abstract method foo() in TestInterface
    public class InterfaceTestClass implements TestInterface {
    ^
    1 error

    C:\Documents and Settings\xmorel\Bureau>javac AbstractTestClass.java

    C:\Documents and Settings\xmorel\Bureau>javac -cp . InheritanceTestClass.java
    InheritanceTestClass.java:1: InheritanceTestClass is not abstract and does not o
    verride abstract method foo() in AbstractTestClass
    public class InheritanceTestClass extends AbstractTestClass {
    ^
    1 error

    Do you notice the difference between the compilation error messages? cause I sure don't (the class names notwithstanding)

    Seems to me that Java's interfaces are implemented as purely abstract classes and that the implements mechanism does with interfaces what extends does with classes.



  • On the other hand, the compiled representation of the class contains a flag indicating whether the class is an interface or not that is separate from whether the class is abstract or not.  The class validator may or may not use this flag to reject interfaces that contain non-abstract methods; I've never bothered to handcraft a .class file containing the equivalent of

      public interface Foo {
        public void fooMethod () {
          System.out.println ("Hi there.");
        }
      }

    Though that'd be an interesting experiment.



  • Erm. Yes. It works that way on purpose.

    Right, and the way it works is inconsistent.

    Interfaces are quite different from multiple inheritance, and are the "proper" way to do it.

    Except they can't do what MI supports.  They're not the proper way to do MI at all, because they can't do MI.

    When you have two superclasses, and both implement a method with the same signature, which one is the VM supposed to call?

    The same is true of interfaces.  Just because two interfaces have the same method with the same signature does not mean that they should have the same implementation.  MS gets this (which is why .NET allows explicit implementations of interface methods), Sun does not.

    Is ((base1)sub).toString() going to return a different result as ((base2)sub).toString()? Can you see the madness that multiple inheritance creates?

    Er.  No, not really.  That they do something different is entirely reasonable.

    <FONT face="Courier New">public interface IFoo
    {
     /// Print a message
     void qux();
    }</FONT>

    <FONT face="Courier New">public interface IBar
    {
     /// format the hard disk
     void qux();
    }</FONT>

    <FONT face="Courier New">public class Baz implements IFoo, IBar
    {
     public void qux()
     {
      // just what the hell do I do here?  I don't IFoo.qux and IBar.qux to be identical
     }
    }</FONT>

    Both interfaces can declare a toString() method, but it's only going to be IMPLEMENTED once.

    Which means that one or other interface gets it wrong.  Just because they share an interface does not means they need to share the implementation.  Java ought to support multiple implementations.

    Interfaces also cannot declare fields;

    Don't be silly.  Of course they can.

    What do you expect the function to print? 1? 2? WHY?! It makes no sense.

    I would expect the compiler to barf because it's ambiguous.  You're right; it makes no sense.  This is why you can't do it.  But if you disambiguate (qualify the member access with the interface name) it works.  If it can be done with fields, which it can, why should it be prohibited for members?  The same solution works for both.  There are other possible solutions, of course; it could for example state that the names are resolved left-to-right.  But simply rejecting out of hand ambiguous accesses seems quite fair.

    Interfaces are DESIGNED to avoid the problems that multiple inheritance causes, while still retaining ALL of their usefulness.

    But they don't.  They don't avoid the problems (because Java's interfaces provide no mechanism for resolving name clashes).  They don't retain MI's usefulness (because they're not MI).



  • Could you maybe give an example, where you needed a class to implement two interfaces (inherit from two classes), and each of them had a method with the same name, that would do different things?

    I honestly can't think of a situation where I'd need that, although I should add that I'm not a professional.

    I mean, if you want them to have the same name, then you probably have a call somewhere where it doesn't matter which of the two is in use (because the classes it's used on implement only one of them and they - kind of - do the same in the context there), and a call somewhere else where it does matter which one is used?



  • It doesn't happen so much with the Sun java classes, but I've had it happen with third party libraries; either clashing with each other or with a Sun class that they didn't think I'd want to implement.  It's not common, but it's common enough.

    The solution, such as it is, is to do something like this:

    <FONT face="Courier New">public interface IFoo
    {
     /// Print a message
     void qux();
    }</FONT>

    <FONT face="Courier New">public interface IBar
    {
     /// format the hard disk
     void qux();
    }</FONT>

    <FONT face="Courier New">public class Baz // does not implement either method
    {
     void IFooQux()
     {
      // etc.
     }
     void IBarQux()
     {
      // etc.
     }
     
     public IFoo asIFoo()
     {
      return new IFoo() { public void qux() { return IFooQux(); } }
     }
     
     public IBar asIBar()
     {
      return new IBar() { public void qux() { return IBarQux(); } }
     }
    }
    </FONT>



  • Think of Java interfaces as if they were COM interfaces.  They serve essentially the same purpose - specifying a known set of methods that an object implements.  (Except, of course, COM provides methods for resolving name clashes, and Java doesn't.)

    @DrPizza said:

    Interfaces also cannot declare fields;

    Don't be silly.  Of course they can.

    No, they can't.  They can declare static fields, but not member fields.

    @DrPizza said:

    What do you expect the function to print? 1? 2? WHY?! It makes no sense.

    I would expect the compiler to barf because it's ambiguous.  You're right; it makes no sense.  This is why you can't do it.  But if you disambiguate (qualify the member access with the interface name) it works.  If it can be done with fields, which it can, why should it be prohibited for members?  The same solution works for both.  There are other possible solutions, of course; it could for example state that the names are resolved left-to-right.  But simply rejecting out of hand ambiguous accesses seems quite fair.

    Except Java links both at compile time (sorta) and at runtime.  It can't know ahead of time what methods will be present in all classes at runtime, because that can conceivably change.  (See, "Sun randomly adding methods to the JDBC interfaces between Java releases.")

    There's a Java error for this case, java.lang.LinkageError, which is thrown by the classloader if a parent class has changed such that a child class can no longer successfully link with it.

    Java resolves method names to implementation code at runtime, so it would have to handle clashes at runtime.  It can't just reject them at compile time, since they can also occur at runtime.

    Generally speaking there are very few instances when you really need multiple inheritance, and it generally just creates problems.  Not that I couldn't use it, mind you - I have an abstract javax.servlet.jsp.tagext.Tag implementation, and it would be really nice to be able to inherit both from that implementation and javax.servlet.jsp.tagext.BodyTagSupport, but... on the other hand, I don't trust the other developers working on the project not to abuse MI if they were allowed it... :)


  • DrPizza: Ah, okay, so you wouldn't use it yourself, if you weren't forced to.



  • No, they can't.  They can declare static fields, but not member fields.

    static fields are member fields; what they're not is instance fields.  A static member is still a member.

    Except Java links both at compile time (sorta) and at runtime.  It can't know ahead of time what methods will be present in all classes at runtime, because that can conceivably change.  (See, "Sun randomly adding methods to the JDBC interfaces between Java releases.")

    There's a Java error for this case, java.lang.LinkageError, which is thrown by the classloader if a parent class has changed such that a child class can no longer successfully link with it.


    Right; and if you attempt to recompile against the new version you'll get a compiler error (always I think?).

    Java resolves method names to implementation code at runtime, so it would have to handle clashes at runtime.  It can't just reject them at compile time, since they can also occur at runtime.

    So we can either introduce a rule (start from the left, for example) or retain the runtime error and force recompilation (thereby forcing the developer to disambiguate, as they must do already).  Either is fine.

    Generally speaking there are very few instances when you really need multiple inheritance, and it generally just creates problems.

    It doesn't "generally" do anything of the sort.  There can be issues with MI (nothing insurmountable, mind you), but *in general* they don't actually arise in real-world uses of MI.

    Not that I couldn't use it, mind you - I have an abstract javax.servlet.jsp.tagext.Tag implementation, and it would be really nice to be able to inherit both from that implementation and javax.servlet.jsp.tagext.BodyTagSupport, but... on the other hand, I don't trust the other developers working on the project not to abuse MI if they were allowed it... :)

    There are so many things for bad developers to screw up it seems to me a particularly poor rationale.  If we excluded features because people might "abuse" or misuse them then we wouldn't have threads, or inheritance, or interfaces, or exceptions (to name a few things).  They're all regularly abused.  Even the most innocuous of features can, in the right (?) hands, be abused.  The existance of this very site is ample evidence of such.  If every abused feature were stripped from a language you would be left with a language which could do nothing.



  • @Xenoveritas said:

    Java resolves method names to implementation code at runtime, so it would have to handle clashes at runtime.  It can't just reject them at compile time, since they can also occur at runtime.

    Java is a statically typed language.  Ambiguities are already rejected at compile time.

    @Xenoveritas said:
    Generally speaking there are very few instances when you really need
    multiple inheritance, and it generally just creates problems.

    Er, speak for yourself.



  • @Chris F said:

    @Xenoveritas said:
    Java resolves method names to implementation code at runtime, so it would have to handle clashes at runtime.  It can't just reject them at compile time, since they can also occur at runtime.

    Java is a statically typed language.  Ambiguities are already rejected at compile time.


    Xeno's point would've been better stated as "It can't only reject them at compile time".  Keep in mind that an interface can be recompiled without forcing the recompilation of implementations.



  • @DrPizza said:

    There are so many things for bad developers to
    screw up it seems to me a particularly poor rationale.  If we
    excluded features because people might "abuse" or misuse them then we
    wouldn't have threads, or inheritance, or interfaces, or exceptions (to
    name a few things).  They're all regularly abused.  Even the
    most innocuous of features can, in the right (?) hands, be
    abused.  The existance of this very site is ample evidence of
    such.  If every abused feature were stripped from a language you
    would be left with a language which could do nothing.



    Sure, but there are some features which have very little utility and a
    great deal of potential for abuse.  (I'd name them but each is
    worthy of a whole new thread.)



    Even single inheritance gets the crap abused out of it on a regular
    basis.  There is no single antipattern more common in Java than
    the use of inheritance where it is not needed.  I'm confident
    multiple inheritance, if available, would be beneficial in only a tiny
    fraction of cases where it would end up getting used.  The
    trade-off isn't worth it, and I honestly think that trade-off was
    something the designers of Java considered.



  • @VGR said:

    Even single inheritance gets the crap abused out of it on a regular basis.  There is no single antipattern more common in Java than the use of inheritance where it is not needed.  I'm confident multiple inheritance, if available, would be beneficial in only a tiny fraction of cases where it would end up getting used.

    I really don't buy this.  MI doesn't get used in C++ that often.  And most of the time it's used it's used reasonably.  I know it's fashionable to rail against it, to mutter about the "dreaded diamond" and generally regard it as some kind of an evil, but *in practice* it isn't.  *In practice* it's either not used (because it's unnecessary), it's used in a way that's harmless (that is not to say it's necessarily "good OO" but it's not actually cauusing any problem), or it's used reasonably.  I read and write a large amount of C++, and if I were to pick a feature to remove because of "abuse", it certainly wouldn't be MI; it gets a lot of bad press, but it's just not deserved.

    (FWIW the feature I would remove is broad syntactic compatibility with C; particularly egregious is the declarator mess, but there are other issues such as its inability to be parsed with any "simple" parser (due to typedefs and templates).  These issues could be fixed, but the syntax would have to change.  The upsides of this would be immense; much better tools (e.g. refactoring support) would be feasible, and it would I hope prevent people writing so-called "C/C++", that is, idiomatic C with enough C++ness to prevent use of a C compiler).

    The trade-off isn't worth it, and I honestly think that trade-off was something the designers of Java considered.

    I think more fundamentally the idea of designing a programming language for skills of the lowest common denominator is misguided.  I don't believe it appreciably improves bad code, nor does it reduce the amount of bad code that exists (bad coders will abuse anything, no matter how constrained the language developers try to make them; preventing them from abusing feature X means only that they vent their incompetence on feature Y).  I do, however, believes that it hurts *good* developers writing good code; they are forced to use inelegant hacks to work around language flaws.

    If the bar at the bottom were raised as the bar at the top were lowered, one might claim that it was a trade-off worth making.  I don't believe that has happened, though.

    Consider another example; checked exceptions.  This (misguided) feature was an attempt to force proper exception handling on people.  It's been an abject failure.  It leads to catch(Exception e) {}, and that ain't "exception handling".  It's just bad, bad, bad.  In actual fact, it makes bad code even worse.  In general it is FAR better to let an exception you can't handle just bubble to the top of the stack (because it's better to do nothing than it is to do the wrong thing) and end the thread.  Yet this *perfectly reasonable* practice is made almost impossible by checked exceptions because of an attempt to make bad coders write better code.

     



  • ah, yes, }catch(IOException e){ throw new RuntimeException(e); } with every IO method that doesn't do this itself already(extra lines of code for every non-standard write to stdout).

    or the more general }catch(Throwable t){
      if((t instanceof RuntimeException) || (t instanceof Error)){
        throw t;
      }else{
        throw new RuntimeException(t);
      }

    really, I'll catch it if I have a use for that, this is soooooo much extra code that actually makes these 'checked' exceptions just slower, unchecked ones.



  • I agree that Java does not benefit from a syntax designed to make C++
    programmers feel at home, but back in 1995, it made all the difference
    in the world.  As it was, Java had a very hard time finding
    adoption.  If there had been a steeper learning curve, I think it
    would have faded into obscurity as quickly as most other novel
    languages of the 90s.



    (I've heard that the original plan was to base Java on Objective C,
    which in my own opinion would have been fantastic.  But even that
    would have killed its chance at widespread acceptance.)



    That said, Java's design employs a philosophy which may be partly a
    "lowest common denominator" philosophy but which is also a "more
    productivity, less bullshit" philosophy.  The goal is to stay as
    simple and straightforward as possible.  (Also known as
    K.I.S.S.)  I've come to really appreciate this, as it makes
    maintenance considerably easier.



    For each syntactic feature, I think it's important to ask, is the
    benefit worth the added complexity?  Just having a benefit alone
    is not enough justification for the feature.  Most people agree
    that C++ did not ask this question, and its complexity got out of hand
    as a result.



    True, multiple inheritance doesn't get abused too often in C++. 
    But there is one major difference between C++ and Java, which leads me
    to believe syntax is much more likely to be abused in Java than in
    C++.  C++ is just a superset of C;  this means that C
    programmers are not under much pressure to use the features of
    C++.  However, Java is a new language, only partly overlapping C++
    in syntax, and traditionally computer science has taught students that
    all languages are interchangeable, each expressing the same things in a
    different syntax.  So when a C or C++ programmer moves over to
    Java, he almost invariably abuses the syntax, as it makes him feel like
    he's "writing things the Java way."  Abusing inheritance is the
    most common manifestation of this.  Overuse of reflection is
    another.  And, yes, abuse of exceptions (such as for flow control)
    is another.






  • @VGR said:

    That said, Java's design employs a philosophy which may be partly a
    "lowest common denominator" philosophy but which is also a "more
    productivity, less bullshit" philosophy.  The goal is to stay as
    simple and straightforward as possible.  (Also known as
    K.I.S.S.)  I've come to really appreciate this, as it makes
    maintenance considerably easier.

    As i understand The Java Philosophy(TM), it's all about keeping code monkeys from doing stupid things regardless of their stupidity. It's about obsessive top-down design, committees and cubicles.

    Yes, the language is as simple as possible. But that's not necessarily straightfoward from a programmers perspective, when you want get things done. And it sure is not "more productive", otherwise we would all code assembler on RISCs.

    @VGR said:

    ... I think it's important to ask, is the
    benefit worth the added complexity?

    How could MI possibly be complex in any sane program? In my humble experience it's quite often the lack of MI that causes complexity.



  • I agree that Java does not benefit from a syntax designed to make C++ programmers feel at home,

    Java probably benefits more from making C++ programmers feel at home than C++ does C programmers.

    but back in 1995, it made all the difference in the world.  As it was, Java had a very hard time finding adoption.

    I don't think so, no.  It did have a hard time finding adoption on the desktop, but it carved out its server role pretty effectively.

    That said, Java's design employs a philosophy which may be partly a "lowest common denominator" philosophy but which is also a "more productivity, less bullshit" philosophy.

    No it isn't.  Not having MI (for example) is not a productivity improver in the slightest.

    The goal is to stay as simple and straightforward as possible.  (Also known as K.I.S.S.)  I've come to really appreciate this, as it makes maintenance considerably easier.

    Which is simpler and has lower maintenance costs?  public class Foo extends Bar, Baz?  Or having to manually forward every single method, with the ongoing maintenance overhead that incurs?

    For each syntactic feature, I think it's important to ask, is the benefit worth the added complexity?  Just having a benefit alone is not enough justification for the feature.  Most people agree that C++ did not ask this question, and its complexity got out of hand as a result.

    C++ is complex first and foremost because it tries to shoehorn a lot of functionality into what is essentially C syntax.  C syntax wasn't even good for C; it's even worse for C++.

    True, multiple inheritance doesn't get abused too often in C++.  But there is one major difference between C++ and Java, which leads me to believe syntax is much more likely to be abused in Java than in C++.  C++ is just a superset of C;

    Is not.

    this means that C programmers are not under much pressure to use the features of C++.

    It is true that C++ can be used as if C.  I am not convinced that this is a good thing, however.  It gives rise to the phenomenon of "C/C++".  This is where people write programs that are essentially C, in the idioms of C, but include just enough C++ to (a) prevent compilation in a C compiler (b) obfuscate their intent entirely.  You know the kind of thing; where classes are added at random, where C-strings are used exclusively, where they don't use the standard library except maybe std::cout; it's extremely common, and it does immense harm to C++.

    However, Java is a new language, only partly overlapping C++ in syntax, and traditionally computer science has taught students that all languages are interchangeable, each expressing the same things in a different syntax.  So when a C or C++ programmer moves over to Java, he almost invariably abuses the syntax, as it makes him feel like he's "writing things the Java way."  Abusing inheritance is the most common manifestation of this.  Overuse of reflection is another.  And, yes, abuse of exceptions (such as for flow control) is another.

    I think this is true, to an extent, but it's far truer in C++.  Especially because C++ provides access to the old C library.



  • @DrPizza said:

    but back in 1995, it made all the
    difference in the world.  As it was, Java had a very hard time
    finding adoption.

    I don't think so, no.  It did have a
    hard time finding adoption on the desktop, but it carved out its server
    role pretty effectively.


    Eventually.  I would say it saw pretty poor adoption during the twentieth century, though.

    @DrPizza said:

    The goal is to stay as simple and straightforward as possible.  (Also known as K.I.S.S.)  I've come to really appreciate this, as it makes maintenance considerably easier.

    Which is simpler and has lower maintenance costs?  public class Foo extends Bar, Baz?  Or having to manually forward every single method, with the ongoing maintenance overhead that incurs?

    How about:

    public class Foo extends Bar
    {
        public Baz getBaz() { ... }
    }

    No need to forward any methods.

    Inheritance is one way to share functionality, but it's not usually the best way, I've found.



  • @VGR said:

    @DrPizza said:

    but back in 1995, it made all the
    difference in the world.  As it was, Java had a very hard time
    finding adoption.

    I don't think so, no.  It did have a
    hard time finding adoption on the desktop, but it carved out its server
    role pretty effectively.


    Eventually.  I would say it saw pretty poor adoption during the twentieth century, though.

    @DrPizza said:

    The goal is to stay as simple and straightforward as possible.  (Also known as K.I.S.S.)  I've come to really appreciate this, as it makes maintenance considerably easier.

    Which is simpler and has lower maintenance costs?  public class Foo extends Bar, Baz?  Or having to manually forward every single method, with the ongoing maintenance overhead that incurs?

    How about:

    public class Foo extends Bar
    {
        public Baz getBaz() { ... }
    }

    No need to forward any methods.

    Inheritance is one way to share functionality, but it's not usually the best way, I've found.



    Or, use a modern IDE (such as Idea) which will create the delegate methods for you. :-)
    As an alternative, you can use a language such as Objective C or Ruby which has a different concept of typing and functionality sharing :-)


  • How about:

    public class Foo extends Bar
    {
        public Baz getBaz() { ... }
    }

    No need to forward any methods.

    Er... what?

    Since that doesn't achieve the same thing as MI would (or forwarding does) how is it a solution?



  • @DrPizza said:

    How about:

    public class Foo extends Bar
    {
        public Baz getBaz() { ... }
    }

    No need to forward any methods.

    Since that doesn't achieve the same thing as MI would (or forwarding does) how is it a solution?


    It does achieve the same thing.  The only reasons to subclass are polymorphism and inheritance of functionality.  You obviously have access to the functionality.  The purpose of polymorphism is, in this case, to let a Foo instance be passed wherever a Baz instance is needed;  instead of the Foo instance actually being a Baz instance, you have to call (gasp) one method to convert it to a Baz instance instead.  (The method might be better named "asBaz()".)

    Yeah, it's more effort.  But it's not that much effort.


  • @VGR said:

    It does achieve the same thing.  The only reasons to subclass are
    polymorphism and inheritance of functionality.  You obviously have
    access to the functionality.  The purpose of polymorphism is, in
    this case, to let a Foo instance be passed wherever a Baz instance is
    needed;  instead of the Foo instance actually being a Baz
    instance, you have to call (gasp) one method to convert it to a Baz
    instance instead.  (The method might be better named "asBaz()".)

    Err, that's not polymorphism and no it doesn't achieve the same thing.  What if the Baz instance needed to take advantage of some internal Foo members as part of the semantics of this relationship?  This is easily achievable with an overridden method.  Keeping them in separate classes is more work, breaks implementation hiding, and compromises encapsulation.



  • It does achieve the same thing.

    Not as it stands it doesn't, no.

    The only reasons to subclass are polymorphism and inheritance of functionality.  You obviously have access to the functionality.

    Not automatically you don't.  You have to write code to forward each and every method.  If a new method gets added, your code just got broken.



  • @DrPizza said:

    It does achieve the same thing.

    Not as it stands it doesn't, no.

    The only reasons to subclass are polymorphism and inheritance of functionality.  You obviously have access to the functionality.

    Not automatically you don't.  You have to write code to forward each and every method.  If a new method gets added, your code just got broken.


    I guess I wasn't being clear.  My point was that you wouldn't forward any methods at all.  Instead of copying every method, you just call the Baz methods.

    Thus, instead of writing code like this:

    Foo foo = new Foo();
    String name = foo.getBazName();
    Date date = foo.getBazDate();

    You would write code like this:

    Foo foo = new Foo();
    String name = foo.getBaz().getName();
    Date date = foo.getBaze().getDate();

    Same functionality, no need for inheritance.  You can argue that you absolutely must override both methods of Bar and methods of Baz, in one class no less, but as a design reviewer I'd need a better argument than "I really want to use inheritance to do this."


  • @VGR said:



    You would write code like this:



    Foo foo = new Foo();

    String name = foo.getBaz().getName();

    Date date = foo.getBaze().getDate();



    Same functionality, no need for inheritance.  You can argue that
    you absolutely must override both methods of Bar and methods of Baz, in
    one class no less, but as a design reviewer I'd need a better argument
    than "I really want to use inheritance to do this."


    Your example is bad style, it violates the Law of Demeter.



  • @ammoQ said:

    @VGR said:


    You would write code like this:



    Foo foo = new Foo();

    String name = foo.getBaz().getName();

    Date date = foo.getBaze().getDate();



    Same functionality, no need for inheritance.  You can argue that
    you absolutely must override both methods of Bar and methods of Baz, in
    one class no less, but as a design reviewer I'd need a better argument
    than "I really want to use inheritance to do this."


    Your example is bad style, it violates the Law of Demeter.

    I disagree.  The Law of Demeter often contends with the basic principles of encapsulation.  If there really is a HAS_A relationship between Foo and Baz, it is usually far more maintainable to treat Baz as a distinct entity.  Especially when there are a lot of relationships between entities.



  • @ammoQ said:

    @VGR said:


    You would write code like this:



    Foo foo = new Foo();

    String name = foo.getBaz().getName();

    Date date = foo.getBaze().getDate();



    Same functionality, no need for inheritance.  You can argue that
    you absolutely must override both methods of Bar and methods of Baz, in
    one class no less, but as a design reviewer I'd need a better argument
    than "I really want to use inheritance to do this."


    Your example is bad style, it violates the Law of Demeter.


    Extending a class does no more to hide it than the accessor method does, though.



    I agree it's bad form, unless Baz happens to be immutable (or is easily and cheaply cloned).



  • @VGR said:



    Extending a class does no more to hide it than the accessor method does, though.

    When a class is extended, there is no point in hiding the methods of the ancestor class. We would not need class inheritance if we wanted to hide the ancestor.



  • We've seem to have generated yet another Java-vs-C++ flamethread here, which is a pity because both are very fine languages each based on different, not to say opposing, philosophies and geared toward different set of problems. As I have argued before here, this is less a clash of languages than a clash of worldviews.

    • C++ is designed for maximal freedom for the programmer, to provide him with the fullest possible toolset for him to chose from when approaching the problem at hand, well aware of that he has the full freedom to shoot himself horribly. C++ trusts the programmer to know what to do. In other words, C++ was made with the classical hacker in mind.


    • Java was originally designed for accessability and low entry barriers and less steep learning slope. The design behind Java is one of not trusing the programmer by restricting his options, which also means less ways for him to maul himself. Java was made more for "users", that is, the term traditionally used to describe non-hacker computer users and programmers.

    Thus, we have a "freedom vs. restrictions" (which, to go off on a wild tangent,  is highly interesting given the current developments in American social structures, culture and politics) rather than a "my language can beat up your language" conflict, which in an absurd way is more rational since both languages are well-featured turing-complete languages of such power that you not only can theoretically make similar things in both (for most problems), but that you can so practically too, and with relative easy to boot.

    From its multi-paradigm approach and feature set C++ is thus a language designed for power and versitility. The question is thus, "is this power and versitility really needed?" If you by the question mean, "can it be done in another way?", then the answer is "no, it isn't needed". But if you mean "are there programmers who desire this versitility" or "does it simplify for programmers?", then the answer is "yes, it is needed". And again, it is here that the C++ and Java designers have interpreted the original question differently: when asked "is it really recessary to have several ways to achieve similar things?" C++ answered "yes" while Java answered "no". Neither answer is right or wrong, they are indiciative of different philosophies.

    One of the reasons for the freedom approach of C++ is to relieve the programmers of most possible sources of tedium, and this is one of the main benefits of multiple inheritence. Let's face it, one major annoyance of writing real-life Java code is that you have to implement and re-implement that which is specified in the interfaces, and this grows tedious fast. And of cource there are ways around this, f.i. by composing inner or proxy or anonymous or whathaveyou classes, which works, but is less user-friendly than the original specification would have it and messes up the code aesthetics. Or you can reimplement the code time after time, watch your code base grow, and lose part of that holy ideal of "no code duplication".

    This is not to say the languages are equivalent, they are geared to dofferent problem sets, and provides different tools for these. And one of the fulcrum differences is multiple inheritance, and another is templates. C++ templates are NOT the same as Java generics, which by the way can be argued to be a slight misnomer since they do not allow full genericity unlike templates: C++ templates are tools for fully generic code.

    Unfortunately, this won't mean much to you unless you already know what I'm talking about, but Where C++ really shines is when you combine facilities like multiple inheritence with templated metaprogramming for compile-time source generation, then you can acheive some of the most generic, aesthetic, efficient code currently possible both for performance and code minimisation/reusability. Java simply has no similar facilities. To find somthing similar in non-binary-compiled languages we rather need to go to the wonderful language Ruby, with its mix-in capacities. Again, it this really necessary? No. Is it a Good Thing? I definitely think so.

    @Nandurius said:
    Coming from a Java background, I haven't run into any situations yet where I would've wanted to have multiple inheritance. [...] My thought is that those who are used to C++ use it, effectively, and structure their programs in ways to take advantage of it. Those used to Java use interfaces instead, structure the programs to take advantage of interfaces, and that works just as well.


    To an extent, Nandurius answers the debate himself - these kind of conflicts more often arise from different background and experiences: the most vociferous antagonists from both camps are often those with the least (if any) experience, except superficial at best, of that they criticise. It is our prior experiences and expectations which determines our reactions and sentiments toward The Other: divergence gives dissonance, dissonance yields dislike. Where I disagree, however, is with the claim that both the Java and C++ inheritence models, or rather, full MI vs MI of interfaces only, work just as well: they are different appraches which can be applied to create similar but not equivalent solutions. The end result will probably function similar (the user does not know whether the program is written in C, Fortran, Ruby, D or Java) but the underlying code and chosen solution will differ, and well-designed MI will generate efficient, beautiful, easily maintained and terse code.

    Turning to the more specific claim:
    @Nandurius said:
    Interfaces are DESIGNED to avoid the problems that multiple inheritance causes, while still retaining ALL of their usefulness.

    This has already been answered, but I might summarise.

    • MI of interfaces do nor retain the full usefulness of full MI: with full MI you do not need to reimplement the bodies (but you can if you wish), which preempts tedium and decrease code duplication.

    • MI of interfaces only is not free from full MI's problems, as shown in posts above, this code will not work.
    <font face="Courier New">interface base1 {</font>
    <font face="Courier New">    public int myValue = 1;</font>
    <font face="Courier New">}</font>
    <font face="Courier New">interface  base2 {</font>
    <font face="Courier New">    public int myValue = 2;</font>
    <font face="Courier New">}</font>
    <font face="Courier New">class sub implements base1, base2 {</font>
    <font face="Courier New">  public String toString() {</font>
    <font face="Courier New">       return "My value is " + myValue;</font>
    <font face="Courier New">  }</font>
    <font face="Courier New">}</font>
    • Multiple inheritence causes no problmens per se in real-life code. I've worked with the language for ~15 years and have still to see this chimeara outside the newbies first computer class. And their Java code isn't very pretty, either. This is a tenacious myth, and one without any substance.

    • Full MI is fully functioning without hassle for the programmer in many languages, not only C++, using verious solutions. That Java does not feature full MI is not to avoid problems for the programmers -in fact, teaching Java has proved to me that interfaces is in fact a more difficult concept than multiple inheritance!- but to avoid problems for the language bytecode compiler developers. Again, difference in philosophies, Stroustrup said: "when chosing between inconveniencing the programmers and inconveniencing the compiler developers, always choose the second". In the example above, the solution to this problem in C++ is so trivial that it hardly deserves mention: qualifying the multiply included member as either base1::myValue or base2::myValue.



  • @Mikademus said:


    • C++ is designed for maximal freedom for the programmer, to provide him with the fullest possible toolset for him to chose from when approaching the problem at hand, well aware of that he has the full freedom to shoot himself horribly. C++ trusts the programmer to know what to do. In other words, C++ was made with the classical hacker in mind.

    • Java was originally designed for accessability and low entry barriers and less steep learning slope. The design behind Java is one of not trusing the programmer by restricting his options, which also means less ways for him to maul himself. Java was made more for "users", that is, the term traditionally used to describe non-hacker computer users and programmers.


    I don't think Java is targeted towards less sophisticated programmers. The restrictions in Java IMO make it easier to build large apps without hunting the bugs C or C++ allow for. Even the most buggy java class cannot produce the kind of random side effects a single twisted pointer causes in C or C++.



  • Darn, time limit on the edit function. Well, you'll just have to live with my spelling errors then...

    @ammoQ said:

    I don't think Java is targeted towards less sophisticated programmers. The restrictions in Java IMO make it easier to build large apps without hunting the bugs C or C++ allow for. Even the most buggy java class cannot produce the kind of random side effects a single twisted pointer causes in C or C++.


    Oh, it certainly isn't primarily intended for newbs anymore, Java's evolution has been such that it is almost as complicated now as C++ only in different ways/ares, but it is still a very common argument that "C++ is a bad language because the learning curve is too steep while Java is a good language because it is easy to learn". Java was easy (easier) to learn. However, from teaching exdperience I tell you that the current Java is quite tough on the n3wblars. And with the rampant extensions to Java it can get quite bloody finding the bugs - I've seen some horrendous things done with introspection and/xor aspects in production Java code that renders debugging layered templates honest-to-god recreation in comparison.

    As for pointers, yet again the old principle: fabulous power entails the possibility of horrible disasters. Therefore, teach and trust programmers to be judicious. Or the other way around, rely too much on the language to save you and you will never write good code. Good examples are the meaningless catch / throw blocks sprinkled through most Java code, as discussed in posts above. Still, that is a much better example than claiming that MI leads to dangerous code.



  • @ammoQ said:

    @Mikademus said:

    • C++ is designed for maximal freedom for the programmer, to provide him with the fullest possible toolset for him to chose from when approaching the problem at hand, well aware of that he has the full freedom to shoot himself horribly. C++ trusts the programmer to know what to do. In other words, C++ was made with the classical hacker in mind.

    • Java was originally designed for accessability and low entry barriers and less steep learning slope. The design behind Java is one of not trusing the programmer by restricting his options, which also means less ways for him to maul himself. Java was made more for "users", that is, the term traditionally used to describe non-hacker computer users and programmers.


    I don't think Java is targeted towards less sophisticated programmers. The restrictions in Java IMO make it easier to build large apps without hunting the bugs C or C++ allow for. Even the most buggy java class cannot produce the kind of random side effects a single twisted pointer causes in C or C++.

    And yet the complete and utter absence of restrictions of Smalltalk, Ruby or Python coupled to easy testing make it easier to build large apps without having to jump through bug-generating hoops java requires to go through.

    Most languages are enablers, they allow you to do thing, Java is one of the few disablers, it forbids you to do things "just cause" or "for your own good"... and we know how good things done for your own good are...



  • <font face="Arial">Since this thread is quite rational and sane I'd like to summarise and answer the typical arguments raised against MI:


    0) MI is conceptually complicated.

    </font><font face="Arial">False. Teaching Java and C++ has shown that MI is no more difficult to understand than SI. In fact, the concept of interfaces is more difficult to explain since it (a) requires that inheritance has already been explained and understood, and (b) is less "natural" and cannot, unlike inheritence, be presented without immediately bringing pragmatic progamming issues into the explanation. </font>
    <font face="Arial">

    1) Java hasn't implemented MI to avoid complexity issues

    </font><font face="Arial">False. Java has implemented MI of interfaces which basically entails a full implementation of multiple inheritance. Though interfaces and classes aren't similar (interchangeable) when programming, their underlying implementation are.</font>
    <font face="Arial">

    2) MI results in bad code and errors.

    </font><font face="Arial">False. A very vague argument never further substantiated in the debates. A chimera often touted but never proved. Pragmatic experience shows no such evidence. </font>
    <font face="Arial">

    3) MI results in more complicated and difficult to understand code.

    </font><font face="Arial">False. There is no conceptual-representational difference between a class inherited from multiple classes or multiple interfaces. In fact, the implementation of SI code mimicing some aspects of MI can be much more complicated than the corersponding MI code. </font>
    <font face="Arial">

    4) MI results in code difficult to maintain.


    </font><font face="Arial">False. Classes inherited from multiple classes can even have fewer update points than those from multiple interfaces, which often results in code duplication in real-life code. </font>
    <font face="Arial">

    5) MI of interfaces preserves the benefits of full MI.

    </font><font face="Arial">False. The only feature preserved is polymorphism. Examples of benefits not transfered are code minimisation, code maintainability and straightforward representation of natural relations by inheritence without composition or code duplication. </font>
    <font face="Arial">

    6) MI leads to reduced productivity while SI coupled with MI of interfaces leads to increased productivity.

    </font><font face="Arial">False. MI used properly reduces menial code writing and avoids the convoluted, abstruce or elaborate code constructs lack of the facility often forces. Conversely, reimplementing interfaces has been shown to be a productivity sink. </font>
    <font face="Arial">

    7) MI is unnecessary since everything that can be be done with MI can be done with SI.


    </font><font face="Arial">Logically true, though a turing tarpit argument. Pragmatically, however, MI is a powerful tool for efficient representation of relationships without code duplication or complex code anatomies. Thus identical applications can be made but not in equivalent ways.</font>



    It should also be mentioned that this is a topic principally only raised in Java-vs-C++ flamefests. Very few detractors of Lisp, Python, Perl or Eiffel attacks those languages for supporting multiple inheritance.

    Finally, while not being in any way an Eiffel afficionado, from Eiffel's pages:

    "Don't believe those who tell you multiple inheritance is tricky; that's true only in languages that don't support it, or don't support it well."

    "as anyone who has observed Java and Smalltalk programmers knows, removing multiple inheritance from an O-O language leads programmers to emulate it manually through the kind of tricks that should not be further described in a family-oriented column. By the way, please do not pay attention to anyone who tells you that multiple inheritance is inherently "bad" or "dangerous" or "messy". There is one and only one reason Java and .NET don't have MI: it makes dynamic class loading far more difficult to implement. Every other reason is a red herring."



  • @Mikademus said:

    Darn, time limit on the edit function. Well, you'll just have to live with my spelling errors then...

    @ammoQ said:
    I don't think Java is targeted towards less sophisticated programmers. The restrictions in Java IMO make it easier to build large apps without hunting the bugs C or C++ allow for. Even the most buggy java class cannot produce the kind of random side effects a single twisted pointer causes in C or C++.

    Oh, it certainly isn't primarily intended for newbs anymore, Java's evolution has been such that it is almost as complicated now as C++ only in different ways/ares, but it is still a very common argument that "C++ is a bad language because the learning curve is too steep while Java is a good language because it is easy to learn". Java was easy (easier) to learn. However, from teaching exdperience I tell you that the current Java is quite tough on the n3wblars.


    Well, the java community (if we call it so) has a tendency to use an average of approximately 3.7 million different "frameworks" for any program, including "hello world". For that reason, programming contemporary java applications has become more difficult (in relation to the problems they solve) than anything I've seen in any other language. That's life.



  • @ammoQ said:


    Well, the java community (if we call it so) has
    a tendency to use an average of approximately 3.7 million different
    "frameworks" for any program, including "hello world". For that reason,
    programming contemporary java applications has become more difficult
    (in relation to the problems they solve) than anything I've seen in any
    other language. That's life.


    Amen to this.  I'm having this very problem right now, and it's at
    least the twelfth time I've had to deal with it.  People
    constantly want to pile on unnecessary frameworks.  Apparently
    they see nothing wrong with a classpath that's 2K or even larger. 
    From what I can tell, the mentality at work is that people consider the
    benefits, however small or large, of bringing in a framework without
    stopping for one moment to consider the penalties, particularly that
    mammoth of a penalty that is dependency.  So every framework used
    is seen as a plus.



Log in to reply
 

Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.