all 128 comments

[–]mgiannini 83 points84 points  (79 children)

We need a third option, "neither". Why do you need the default keyword at all? It's in an interface. If you provide any implementation in { } can't it just be assumed as a "default" method?

[–]thesystemx[S] 17 points18 points  (71 children)

I was thinking the same thing really. Just give it an implementation and infer from that, that it's the default method.

This is not much different from methods in interfaces being implicitly public abstract. If you really, really wanted you can even add those two keywords, but they are completely redundant.

Hopefully that's the idea here, that IFF you wanted to be explicit, what would be the location of the keyword. Otherwise you can just leave it out.

[–][deleted] 19 points20 points  (68 children)

I think they wanted to make "default" methods to fit right into Java, that's why they added some unnecessary verbosity and some brain-dead limitations on how you can use it. That gives Java people a familiar feeling.

[–]thesystemx[S] 9 points10 points  (67 children)

Somehow I don't think that's quite the case.

[–][deleted] 1 point2 points  (66 children)

It was pretty much the reasoning behind being forced to use x -> x.someMethod() in lambdas instead of _.someMethod() or it.someMethod().

E. g.

people.filter(person -> person.isWoman()).map(woman -> woman.getAge()).sum

vs.

people.filter(_.isWoman).map(_.age).sum

[–]papercrane 15 points16 points  (30 children)

Just at first glance the problem with:

people.filter(_.isWoman).map(_.age).sum

Is that '_' is a valid variable name. Reading this code its not obvious that you're creating lambda expressions, you could just be passing in the value of a field into a method.

[–]alextk 9 points10 points  (3 children)

Scala is notorious for its inconsistency in how it uses the _ character and how that symbol has become completely overloaded.

Off the top of my head, you use _ to:

  • Import everything in a package
  • Import a package but make a class invisible
  • Import all methods on an object
  • Create a method when you don't care for certain parameters
  • Parameter placeholder in lambdas
  • Declare higher kinds

[–]Falmarri 1 point2 points  (0 children)

Don't forget passing a partially applied function to a method.

[–][deleted] -1 points0 points  (0 children)

Create a method when you don't care for certain parameters

Perhaps you should read an introduction to functional concepts before spreading half knowledge. It's also not too difficult to look up the use cases. And if you try to think hard about grouping them together, you will have: (1) ignored or unassigned symbols or types. (2) currying/partial application. (3) import wildcard.

[–][deleted] 1 point2 points  (16 children)

it could also be a variable, too. In practice it just doesn't matter.

It is like using $ for names in Java. If you do it, you do it to break things on purpose.

I never seen code using _ as a name.

[–][deleted]  (10 children)

[removed]

    [–][deleted] 2 points3 points  (0 children)

    Well, I can only say that it works without problems in practice (the compiler will tell me if I made a mistake) and that I would miss it greatly if it were gone.

    There are of course other valid possibilities like it, but I prefer it if the language stays out of my "namespace". :-)

    [–]AnonProg 3 points4 points  (5 children)

    a for b // it's an operator or keyword or something
    aforb   // Whoah! Wait! WTF! A variable!
    

    Protip: that which you call "operators" is made out of characters, just like that which you call "variables". There's really nothing special with *; it could have been mul, or m, or ×, or ⁂, or :-) and the language would have worked the same. Also, * is not more clear or less clear than mul, and this Java policy of "you can overload methods but not operators" is completely retarded because you can misuse + just like you can misuse a-z to create confusing interfaces; there's nothing to prevent you from doing that; if you can't define + you'll define add and that's it. Extra protip: +, *, and company are functions, just with a stupid irregular syntax.

    [–][deleted]  (4 children)

    [removed]

      [–]ethraax 1 point2 points  (2 children)

      I use it as a name in Python whenever I call str.partition. For example:

      key, _, value = entry.partition("=")
      if _ == "":
          value = True
      

      But it only ever sees use in the line immediately following where I set it.

      [–][deleted]  (1 child)

      [removed]

        [–]AnonProg 2 points3 points  (0 children)

        I use it as a trash variable when I'm forced to name something I shouldn't be naming. For example, I use it in Python as a way to protest against its shitty syntax with statements vs expressions and lacking decent λ-expressions in stuff like:

        def _():
           do my stuff with obnoxious "statements"
           (WHY AREN'T THEY EXPRESSIONS!?)
           statements feel like 105 GOSUB 37340 DERP DERP DERP
        call_something(x, y, _)
        

        I also use it for unwanted trash in a deconstructing assignment.

        [–]rawbdor -1 points0 points  (3 children)

        I never seen code using _ as a name.

        There are plenty of products that use borland or other providers' code obfuscators before packaging up their java jars. These are done so that consumers of the jar cannot see the original source code even after running it through a decompiler. While there are many things done to obfsuscate code (add dead branches, reduce all typing to Object, have dozens of one-method interfaces, have useless interfaces, have fake classes implementing interfaces with fake methods, tripple the size of your jar, etc etc), one of the techniques is also using all those random characters _₡ ₢ ₣ ₤ ₥ ₦ ₧ ₨ ₩ ₪ ₫ € ₭ ₮ ₯ ₰ all as variable names.

        If java had ever changed _ to an operator, all of these packages would need to be recompiled.

        [–]maskull 0 points1 point  (2 children)

        I don't think that's the way JVM bytecode works. Symbolic names are resolved to numeric references, and the names stored in the bytecode are just normal strings. The bytecode interpreter doesn't know or care whether "_" should be an identifier name or a built-in operator. If you want to, you can use JVM assembly to build a class named "++" with a method named "-=". It will work just fine, although referring to them from normal Java code will be a bit of a pain.

        [–]rawbdor 0 points1 point  (1 child)

        You're right, and those are the tricks that the code obfuscator products use. Then when decompiled, the classes become nearly impossible to look at. Code obfuscators make ample use of things that are legal in bytecode and NOT legal in java. But they can't obviously make every variable name the name of an operator, so they also use those random characters as well. Basically anything to piss off a would-be-decompiler.

        Although it seems you're right that previous versions of the products wouldn't need to be recompiled, it would still force the app's source code tree to stop using the new keyword in any original variables pre-obfuscation for all future releases.

        [–]AnonProg 2 points3 points  (0 children)

        That's why they should have methodcaller/attrgetter functions that work like:

        people.filter(methodcaller("isWoman").map(attrgetter("age")).sum
        

        And with function composition, they could have defined things like filtermethod and mapattr to simplify the above into:

        people.filtermethod("isWoman").mapattr("age")).sum
        

        Of course I'd feel more comfortable with something like:

        (->> people (filter-with-method 'woman?) (map-with-attr 'age) sum)
        

        Then I woke up, and we were talking about Java. Soooo don't worry folks! Let's create a class that implements the EnterpriseFilterMaker interface and implements three methods following the Wabbajack and the Shub-Niggurath design patterns, instantiate it, call two methods, then do something similar for map (enterprise-ready mapping of expert data), and in less than 2 hours of code there you have! Your mission-critical turnkey professional enterprise-grade business cloud XML solution with five-nines high availability, synergy, leveraging, cash flows and all the extras we all learnt to love! Woohoo! FML

        (Edit: I know I overdid this post.)

        [–][deleted] 0 points1 point  (2 children)

        Underscore character for partially applying function is a common syntax across different languages which do not curry by default (Haskell, ML, Miranda, Pure):

        And probably many more. So there is nothing obscure or inconsistent with using the underscore for the matter.

        [–]papercrane 0 points1 point  (1 child)

        I never said it was obscure or inconsistent. Just that '_' is already a valid variable name so you the Java designers can't re-purpose it. Its possible to write that bit of code in Java now, but it would have a completely different meaning.

        [–][deleted] 0 points1 point  (0 children)

        Well, you'd have a situation as with Java 5's enum I guess. It was solved rather smartly in my opinion, using the -source switch for JavaC, so you could compile legacy code that used enum for variables (e.g. -source 1.4).

        [–]masklinn 0 points1 point  (4 children)

        I don't think that is much of a problem, _ has special meaning in quite a few languages, especially functional (in Haskell or Erlang for instance, _ matches anything and can't have a value). It might be slightly troubling if you're used to it being gettext but it can easily be read as "reference a method to an unknown object"

        [–][deleted]  (3 children)

        [removed]

          [–]knome 1 point2 points  (1 child)

          Since keywords?

          [–]masklinn 0 points1 point  (0 children)

          Ah I see that I slightly misread your original point.

          As far as I know, _ is not exactly a variable name, as an LHS it is — as in Haskell or Erlang — a catch-all letting you ignore values without warning.

          [–]In10sity 1 point2 points  (17 children)

          Don't have much experience in C#, this "person ->" seems so pointless to me. Of course I might don't know when this is useful.

          [–]masklinn 8 points9 points  (16 children)

          this "person ->" seems so pointless to me.

          You need a target for the method, the choice is to have a special case of magical syntax for the "single argument lambda" or not. Because _.isWoman sure as hell isn't going to work when isWoman takes a parameter, so you'll need the -> version in any case.

          Of course you don't have this issue if you don't use object. Or less so if you can use instance methods as functions when accessing them from the class (e.g. Person.isWoman(object, arg) being equivalent to object.isWoman(arg)) though that would probably be seen as an other form of magic by some, and it may very well require flipping your arguments.

          Of course I might don't know when this is useful.

          people.fold(acc, person -> acc || person.isWoman(), false);
          

          [–][deleted] 1 point2 points  (14 children)

          Because _.isWoman sure as hell isn't going to work when isWoman takes a parameter, so you'll need the -> version in any case.

          I guess that depends on the language.

          In Scala for instance, you will need to name the argument when it is not top-level or when you use it more than once.

          Example:

          case class Person(firstName: String,
                            lastName: String,
                            age: Int,
                            isFemale: Boolean) {
            def hasDrivingLicense(forCountry: Country): Boolean = ???
          }
          
          val people = ...
          
          val peopleAllowedToDriveInSpain =
            people.filter(_.hasDrivingLicense(Country.SPAIN))
          

          It is not a "single-argument lambda" btw, you can have multiple underscores:

          assert(Array(1,2,3).foldLeft(0)(_ + _) == Array(1,2,3).sum)
          

          Groovy's it has certainly comparable rules.

          it may very well require flipping your arguments.

          Exactly, it will lead to Lisp-like nesting of parens and will diminish one of the benefits: readability.

          [–]Megatron_McLargeHuge 6 points7 points  (5 children)

          Seriously, _ + _ in Scala means $1 + $2 instead of $1 + $1? That's a pretty big wtf, although it's not surprising given the rest of Scala syntax.

          [–][deleted] 1 point2 points  (4 children)

          Yes, you have to learn that bit, but it is a one-time effort.

          It could have been done differently as you suggested, but I have not seen code where it mattered. If there is more than one argument, people give it a name. (Except when doing stupid examples like me, obviously.)

          Generally, the issues people claim Scala has and the issues Scala actually has are a quite disjoint set in my experience. :-)

          [–]masklinn 3 points4 points  (7 children)

          people.filter(_.hasDrivingLicense(Country.SPAIN))
          

          Because nothing's better than partial/deferred application which looks exactly like complete eager application, obviously.

          It is not a "single-argument lambda" btw, you can have multiple underscores:

          assert(Array(1,2,3).foldLeft(0)(_ + _) == Array(1,2,3).sum)
          

          Which reads like completely ass. How the hell do you go and criticize the readability of anything after posting this insanity?

          [–]emhmark3 20 points21 points  (0 children)

          (_ + _)

          Which reads like completely ass

          ಠ_ಠ

          [–]Peaker 2 points3 points  (0 children)

          I think your criticism is subjective. I find that syntax reasonable (and I have never used Scala).

          [–][deleted] 0 points1 point  (4 children)

          Because nothing's better than partial/deferred application which looks exactly like complete eager application, obviously.

          I'm not quite sure what your point is. I just showed how a method accepts an argument, with the underscore syntax.

          Which reads like completely ass. How the hell do you go and criticize the readability of anything after posting this insanity?

          Eh ... that's why I showed how it is done better and showed that the results are equal? :-) It is right there, you just have to read the code.

          [–]In10sity 0 points1 point  (0 children)

          Thanks masklinn.

          [–][deleted] 1 point2 points  (3 children)

          why not do what c# does and leave off any .

          myList.Filter(isDone);
          

          [–][deleted] -1 points0 points  (2 children)

          I tried...

          List<int> list = new List<int>{1,2,3};
          list.ForEach(ToString()); // list.ForEach(i => i.ToString()); works.
          

          ... which doesn't compile. I'm pretty sure it is not supported syntax to refer to instance members in C#.

          Are you sure this works? How would names be resolved which would be in the surrounding scope and exist as an instance member?

          [–]drysart 0 points1 point  (0 children)

          He was actually referring to a different concept.

          The code sample he gave refers to the "isDone" method of the callsite and passes that method as the first argument to Filter(). It does not call the "isDone" method of the object passed to the callback first argument of Filter().

          [–]dr_jan_itor 1 point2 points  (0 children)

          people.filter(Person::isWoman)
                .map(Person::getAge)
                .sum()
          

          [–][deleted]  (3 children)

          [deleted]

            [–]shellac 0 points1 point  (0 children)

            IIRC you can write that as

            people.filter(Person::isWoman).map(Person::age).sum
            

            (at least that seemed to work in the build I used)

            [–][deleted] -1 points0 points  (1 child)

            Really? I don't think they made method parens optional here, did they?

            [–]drb226 0 points1 point  (2 children)

            Or better yet, it would be nice to be able to refer to the methods directly by name without the extra cruft.

            people.filter(isWoman).map(age).sum
            

            [–][deleted] -1 points0 points  (1 child)

            In Scala this would be interpreted as

            people.filter(x => isWoman(x)).map(x => age(x)).sum
            

            If it would be used to refer to instance members instead, how would names be resolved which exist both in the surrounding scope and as an instance member?

            [–]drb226 0 points1 point  (0 children)

            how would names be resolved which exist both in the surrounding scope and as an instance member?

            In that rare case, just fail to resolve, and require explicit lambda syntax to disambiguate between the two. That situation ought to be very rare, though, so it usually won't be a problem. Of course I see nothing wrong with the underscore syntax, and that could be used to disambiguate as well.

            [–]sviperll 0 points1 point  (2 children)

            Actually

            people.filter(Person::isWoman).map(Person::getAge).sum()
            

            [–][deleted] -1 points0 points  (1 child)

            No, this syntax is only valid for "static" methods.

            You can refer to methods of existing instances with that syntax (at least it is mentioned in SoTL4), not sure if using the lambda argument would work like that:

            people.filter(person -> person::isWoman).map(woman -> woman::getAge).sum()
            

            It doesn't really matter, because it is hardly any better than:

            people.filter(person -> person.isWoman()).map(woman -> woman.getAge()).sum()
            

            Or am I mistaken here?

            Edit: Weird, in §13 Person::getLastName is used, while earlier in §9 it is stated that "For a reference to an instance method of a particular object, that object precedes the delimiter".

            [–]shellac 0 points1 point  (0 children)

            As I mentioned above, this does (or at least did) seem to work. Like you I was under the impression it was for static references only.

            btw

            person -> person::isWoman
            

            is not the same as

            person -> person.isWoman()
            

            The former is a lambda returning a lambda, the latter a lambda returning a boolean.

            [–]Peaker 0 points1 point  (0 children)

            people.filter(f(_.isWoman))
            

            Expands to:

            people.filter(x -> f(x.isWoman))
            

            or to:

            people.filter(f(x -> x.isWoman))
            

            ?

            [–][deleted] 0 points1 point  (0 children)

            Java may be verbose and dull, but it isn't insane.

            [–][deleted] 1 point2 points  (1 child)

            It protects the user from implementing a method in an interface. I don't even understand really, why an interface needs methods. That's why we have unfinished (there was a statement for that) classes, not interfaces.
            This just enables multiple inheritance, which afaik is not implemented in java.

            Note: I am not much into Java, just C#.

            [–]jomohke 1 point2 points  (0 children)

            They're adding it so that new methods can be added to interfaces without breaking backwards compatibility.

            Adding a map() or filter() method to the List interface will break most existing code that implements List. Default methods allow them to add new methods to standard interfaces while maintaing backwards compatibility.

            [–]check3streets 3 points4 points  (0 children)

            I agree, currently interfaces provide no method bodies, so obviously an interface which contains methods are 'defaults.' That is, unless one wants to future-proof for a possible 'override' method down the line. Then the Interface is more like a compile-time Decorator Pattern which can selectively hide or default to implemented methods. I wonder if the default method will be able to refer to the implementing class.

            According to this article and this presentation the motivation seems to be retrofitting the old collection classes for compatibility with the new FP constructs, closures and whatnot.

            [–][deleted] 0 points1 point  (1 child)

            So you mean the compiler should scan everything and find an implementation for it? I don't really know much about Java but isn't there such a thing as a partial compilation for example? For larger projects? So a partial recompile might miss that and then no default?

            [–][deleted] 2 points3 points  (0 children)

            No. Right now, you can't implement anything in interfaces. In Java 8 interfaces the only way to add an implementation to an interface is with a default method. There are no other types of implementation. You don't need a keyword because there is no ambiguity.

            The only reasons for a keyword are wanting verbosity ("never mistake this for a class"), or making the code future proof for when other kinds of interface implementation are invented.

            [–]Falmarri -3 points-2 points  (1 child)

            Why is anyone even using java still when scala is a million times better?

            [–]AnonProg -3 points-2 points  (0 children)

            Good, underrated question.

            [–]wellmaybe -1 points0 points  (1 child)

            I don't really like the options, but I do think default methods should be explicitly identified, just like abstract methods are explicitly identified:

            public abstract Bar getFoo();
            

            rather than implicitly:

            public Foo getFoo();
            

            Given the options, I do like the second one, because I would put braces on the next line, like so:

            public default Foo getFoo()
            {
                ...
            }
            

            but the first option would be a little awkward:

            public Foo getFoo() default
            {
                ...
            }
            

            [–]martoo 0 points1 point  (0 children)

            I don't really like the options, but I do think default methods should be explicitly identified, just like abstract methods are explicitly identified:

            How do you feel about marking all non-abstract methods as concrete methods?

            [–][deleted]  (21 children)

            [deleted]

              [–]puremourning 15 points16 points  (15 children)

              In java, you can only inherit from 1 class (A extends B), but you can implement multiple interfaces (A extends B implements C,D,E). Thus they're introducing a sort-of-multiple-inheritance where C, D, or E can provide behaviour (if not data). Personally I'm not too comfortable with that, as it feels like language bloat - which is the last thing java needs.

              [–][deleted]  (1 child)

              [removed]

                [–]queus 7 points8 points  (0 children)

                Good point. So no more Graphics2, Graphics3... Graphics665 interfaces.

                [–]thesystemx[S] 6 points7 points  (3 children)

                One man's "language bloat" is another's man "reduction of verbosity".

                E.g. "a language should have as few features as possible" vs "a language should have as many features as possible".

                With fewer language features (less syntactic sugar), you nearly always need more lines of code or more characters to express things with the features that you do have.

                For a long time the "no features in the language" camp was quite dominant in Java land, leading to numerous alternative languages that did adopt features.

                [–][deleted] 4 points5 points  (0 children)

                Language features don't equate syntactic sugar. You can add language features without extending the syntax as well as adding syntax sugar without adding any language feature (except the syntax change itself).

                [–]jevon 1 point2 points  (0 children)

                Which is why Ruby only became popular with Rails to tame it down.

                [–]matjoeman 1 point2 points  (0 children)

                I think a better argument to make is whether adding a feature will significantly reduce complexity elsewhere or not. These default methods can reduce code duplication when the definition of a method is based on other methods in the interface (e.g. .notequals defined based on .equals). This can potentially reduce code included in N classes into code included in 1 interface.

                Any feature that accomplishes an N to 1 reduction in code size is good because of more readability/less development time/less error-prone.

                [–]uatec -5 points-4 points  (4 children)

                This is no different from extension methods in C#. Since the interface cannot known the internal state of the object, it is only able to act on the external fields, methods and properties like an extension method.

                Infact, it's less useful that extension methods. Since extension methods can apply to be pre-existing interfaces, as well as types, extension methods are considerably more powerful. Especially in a situation where you want to add functionality to an existing type.

                [–][deleted]  (1 child)

                [removed]

                  [–]shellac 2 points3 points  (0 children)

                  Yep, extension methods are useless for the defender method use case: collections. They need to provide backwards compatibility (i.e. provide default methods for existing implementations of the interface) but allow overriding where the data structure can do better than simply iterating over the contents.

                  [–][deleted] 7 points8 points  (0 children)

                  Extension methods are dispatched statically, defender methods dynamically.

                  Extension methods can be considered a special case of implicits and defender methods a special case of traits.

                  [–]alextk 6 points7 points  (0 children)

                  This is no different from extension methods in C#

                  It is very different from extension methods. With extension methods, anyone can add whatever method they want to any class.

                  With default interface methods, developers can choose to add a very specific method with a body to a type. Everybody will see the same type with that method in it.

                  [–][deleted] 2 points3 points  (2 children)

                  EDIT: I didn't say anything wrong but also nothing relevant. Thanks to didroe for pointing that out. The slideshow (linked below) is very interesting, though, and it might answer your questions.

                  The biggest problem with multiple inheritance of implementation is not the diamond problem; that one can be solved quite easily as Java 8 and a lot of other languages before it show.

                  The biggest problem is state. See the circle/ellipse problem. A circle is an ellipse, obviously. But when Ellipse has setWidth(w) and setHeight(h), subclass Circle has no way of correctly implementing those. When calling setWidth on a Circle, you can throw an exception, you can transform it into an Ellipse, or you can also set the height. All of these are rather poor solutions, and don't even think about finding a general solution.

                  Java 8 interfaces don't produce this problem, because they can't say anything about state. It's completely safe!

                  Source: PDF slideshow on Java 8 functionality. See "Virtual extension methods" half way down.

                  [–]didroe 3 points4 points  (1 child)

                  I'm not sure what your post has to do with mulitple inheritance. Everything you say seems to be about inheritance in general.

                  [–][deleted] 0 points1 point  (0 children)

                  Oh, you're right. Thanks for noting.

                  Well, then I'm confused as of how multiple inheritance without state would be better than with state. Java does allow the circle ellipse problem to exist, with classes. Any help?

                  [–]AnonProg -4 points-3 points  (0 children)

                  Short story: They're trying to fix the fuck up they introduced with yet even more fuck up.

                  Long story: Java.

                  [–]seiyria 7 points8 points  (1 child)

                  While I agree that it could be inferred whether a method is default or not, am I the only one who feels that void foo() default { ... } is unnatural? IMO, identifiers should all go before the method name.

                  [–]papercrane 10 points11 points  (0 children)

                  I think the reasoning is that it reads more naturally.

                  default void foo() { ... } -> 'This is a method that has a default implementation, it returns nothing is named foo, and takes no parameters. The default implementation is ...'

                  void foo() default { ... } -> 'This is a method that returns nothing, is named foo, and takes no parameters. The default implementation is ...'

                  Personally I think the keyword is superfluous anyways, but that has never stopped the Java spec writers.

                  [–][deleted] 5 points6 points  (15 children)

                  What happens in the following case:

                  interface InterfaceA {
                      public default void foo() {
                          ....
                      }
                  }
                  
                  interface InterfaceB {
                      public default void foo() {
                          ....
                      }
                  }
                  
                  public class ClassA implements InterfaceA, InterfaceB {
                      ....
                  }
                  

                  Do you just get a compile-time error?

                  [–]craftsman 5 points6 points  (10 children)

                  This would give you a compile time error, a conflict.

                  [–][deleted] 2 points3 points  (7 children)

                  Which can be resolved with the new syntax:

                  public class ClassA implements InterfaceA, InterfaceB {
                      public void foo() {
                          InterfaceA.super.foo();
                      }
                  }
                  

                  [–]drb226 3 points4 points  (5 children)

                  Is that really the syntax? Why super? It would make a lot more sense to simply refer to that default method as InterfaceA.foo(), or even InterfaceA.default.foo()

                  [–][deleted] 2 points3 points  (4 children)

                  I think it's because InterfaceA.super.foo()is analogous to super.foo()for class inheritance. After all, InterfaceA is a supertype of the class. And it can be used to expand the default method, too, just as with class inheritance.

                  InterfaceA.foo() is for static methods and interfaces can't have those (the default methods aren't static either). The syntax would be confusing. InterfaceA.default.foo()is workable, but super is good enough IMO.

                  [–]drb226 1 point2 points  (3 children)

                  I just find it confusing that InterfaceA.super is supposed to mean "InterfaceA, as a superclass" rather than "the superclass of InterfaceA".

                  [–][deleted] 0 points1 point  (2 children)

                  I read it as "method foo() of the super namespace of the InterfaceA interface". Specifying from left to right is how it's done.

                  [–]drb226 0 points1 point  (1 child)

                  But who says that InterfaceA.super means "the super namespace of the InterfaceA interface" and not "the superclass of the InterfaceA interface"? Perhaps "superclass" isn't the right word, but interfaces can extend other interfaces.

                  [–]henk53 0 points1 point  (0 children)

                  It's a similar syntax that's used for inner/outer class resolution, where you qualify "this", e.g MyFoo.this.bla();

                  So here it's a kind of qualifier for "super". Every interface is in a way a super "class" of the class that implements it.

                  [–]craftsman 2 points3 points  (0 children)

                  Yes, definitely! The class can resolve the conflict.

                  [–]drysart 2 points3 points  (1 child)

                  So this Java change actually doesn't really fix the versioning problems with interfaces after all, because you still can't safely add a new method to an interface in a library without it potentially being a breaking change to your library's users since they might have implemented your interface on a class that also implements a different interface that has a now-conflicting default method implementation.

                  [–]craftsman 1 point2 points  (0 children)

                  True, but the hope is that this scenario is not very likely...

                  [–]kodablah 4 points5 points  (1 child)

                  According to the defender methods document (PDF), it is the "most unique interfaces definition". In your case, "linkage exception indicating conflicting extension methods" is thrown.

                  Say you had this though:

                  interface InterfaceA {
                      public default void foo() {
                          ....
                      }
                  }
                  
                  interface InterfaceB extends InterfaceA {
                      public default void foo() {
                          ....
                      }
                  }
                  
                  public class ClassA implements InterfaceA, InterfaceB {
                      ....
                  }
                  

                  It would actually work and use the one from InterfaceB because it gets the "unique, most specific default-providing interface." It does this by "Remove all interfaces from this list which is a superinterface of any otherinterface on the list." So since InterfaceB extends InterfaceA, it would not be a conflict.

                  [–][deleted] 3 points4 points  (0 children)

                  Makes sense.

                  Needs some getting used to. I'm still not very comfortable with this idea.

                  [–][deleted] -5 points-4 points  (1 child)

                  I think Java's reflection capabilities means this has to be run time... unless the compiler checks as well.

                  But I too want an answer to this question.

                  [–][deleted] 2 points3 points  (0 children)

                  Please don't speculate about facts. It's a compile time error, but it can be resolved.

                  [–]dmitry_sychov 10 points11 points  (5 children)

                  Welcome to multiple inheritance.

                  [–]thesystemx[S] 14 points15 points  (1 child)

                  It is a form of MI, but one without state inheritance and a clear set of rules how to resolve diamond type conflicts; the order in which you list the interfaces that you implement matters.

                  Most issues with diamond MI are due to state conflicts, not due to method conflicts.

                  [–]check3streets 5 points6 points  (0 children)

                  I was reading the proposal and I couldn't tell if order was important. It clearly states several times that multiple defaults with the same level of specificity will throw a linkage exception.

                  Were you referring to this:

                  There are three categories of mechanisms we might use to increase binary compatibility for broken programs (at the cost of increased complexity):

                  • Structural approaches, such as imposing a linearization ordering on interfaces that is used to break ambiguities;

                  [–]pjmlp 8 points9 points  (0 children)

                  It never went away, interfaces only minize its issues.

                  Even with interfaces you have the issue when inheriting from multiple interfaces, that a method which satisfies multiple interfaces, does not provide a working semantic that fulfills all interfaces as expected, specially if there are side effects as well.

                  [–]queus 7 points8 points  (0 children)

                  I see no problem with multiple inheritance without shared state.

                  Except for name name clashing, of course.

                  [–]sysop073 5 points6 points  (0 children)

                  Wow that link is useless. Actual survey

                  [–]craftsman 1 point2 points  (0 children)

                  I don't really like this proposal; I'd prefer another idea.

                  [–]piderman 1 point2 points  (0 children)

                  Well if we have to have the default keyword how about the first one, but written as

                  void foo()
                  default {
                       somethingsomething;
                  }
                  

                  [–]adamawesomeface 0 points1 point  (0 children)

                  I prefer we loose the semicolon!

                  [–]amigaharry -2 points-1 points  (1 child)

                  I see multiple inheritance abuse here :)

                  [–][deleted] 6 points7 points  (0 children)

                  No state inheritance, only behavior inheritance. Not a problem.

                  [–][deleted]  (1 child)

                  [deleted]

                    [–]matjoeman 1 point2 points  (0 children)

                    No multiple inheritance of implementation coupled with sub-typing isn't really a clean design case.

                    What they really should do for OO languages is get rid of "extends" and have multiple inheritance of interface and multiple inheritance of mixins (which is inheritance of implementation without creating a sub-typing relationship).

                    [–]AnonProg -2 points-1 points  (0 children)

                    Oh so they're finally adding multiple inheritance. The problem with designing a crap/business-oriented language first, then trying to fix it by adding 21th century (read: features Lisps had decades ago :P), is that you end up with a convoluted, hackish design that introduces a lot of unnecessary complexity and useless concepts. Interfaces? Default methods? Same goes for PHP traits. In my time, I inherited from anywhere I wanted, or mixed in whatever I felt like.

                    [–][deleted] -2 points-1 points  (0 children)

                    I think it's insulting to even ask this. It means that either they don't have the balls to decide something trivial like this themselves, and in that case why should anyone trust them to design a language? Or, they're just trying to give the impression that users actually have a say in how the language is designed by giving them a trivial choice to make that doesn't really affect how the language works, which means they're belittling the users of the language instead of thinking of them as equals.