September 30, 2020
On Wednesday, 30 September 2020 at 02:17:37 UTC, H. S. Teoh wrote:
> How is multiple interface broken?

interface A { void foo(); }
interface B { void foo(); }

class C : A, B { void foo() {} }

If there's two interfaces with the same method signature, D merges them by the time you get to the implementation class.

You could argue this is irrelevant and not actually broken but like... idk I see the point.

> Java has multiple interfaces. Are you saying that Java is broken?

Yes, Java does it this way too.

C# doesn't though: there you can specify which interface you want to implement.
September 30, 2020
On Wednesday, 30 September 2020 at 12:34:48 UTC, Adam D. Ruppe wrote:
> On Wednesday, 30 September 2020 at 02:17:37 UTC, H. S. Teoh wrote:
>> How is multiple interface broken?
>
> interface A { void foo(); }
> interface B { void foo(); }
>
> class C : A, B { void foo() {} }
>
> If there's two interfaces with the same method signature, D merges them by the time you get to the implementation class.
>
> You could argue this is irrelevant and not actually broken but like... idk I see the point.
>
>> Java has multiple interfaces. Are you saying that Java is broken?
>
> Yes, Java does it this way too.
>
> C# doesn't though: there you can specify which interface you want to implement.

interface Gun { void fire(); }
interface Rocket { void fire(); }

class Weapon : Gun, Rocket { void fire() {} }

void protectMyself(Gun g) {
  g.fire(); // what did I actually do here?
}

void defence(Weapon w) {
  protectMyself(w);
}

The name might be merged, but semantics aren't the same and sometimes the unexpected happens, that is why Eiffel and .NET languages approach to explicitly state the interface implementations are much better.
September 30, 2020
On 30/9/20 15:37, Paulo Pinto wrote:
> 
> interface Gun { void fire(); }
> interface Rocket { void fire(); }
> 
> class Weapon : Gun, Rocket { void fire() {} }
> 
> void protectMyself(Gun g) {
>    g.fire(); // what did I actually do here?
> }
> 
> void defence(Weapon w) {
>    protectMyself(w);
> }
> 
> The name might be merged, but semantics aren't the same and sometimes the unexpected happens, that is why Eiffel and .NET languages approach to explicitly state the interface implementations are much better.

I would say that this design, at least in the example you proposed, is a bit backwards? I think the following looks better:

```
interface Weapon { void fire(); }

class Gun : Weapon { void fire() {} }
class Rocket : Weapon { void fire() {} }
```

This matches much more the is-a paradigm: a gun is a weapon, a rocket is a weapon, but a weapon is not both a rocket and a gun (well, some weapon might bit, but that most likely would be composition, i.e. a weapon would consist-of a gun and a rocket).

That said, this of course doesn't mean that there are cases where a function with the same name might be defined in two interfaces with different semantics:

```
interface I1 {
    int fun () out (r; r < 0);
}

interface I2 {
    int fun () out (r; r > 0);
}

class C : I1,I2 {
    int fun () {return /* ??? */;}
}
```

Of course, the fact that functions with the same name have different usage is also a bit suspicious, because interfaces should be orthogonal to each other, so I'm not too unhappy that it makes you think twice about it.

That's also why I don't care too much about the extra verbosity that Java promotes (in the method names), it makes this much less likely.

A.
September 30, 2020
On Wednesday, 30 September 2020 at 14:31:56 UTC, Arafel wrote:
> On 30/9/20 15:37, Paulo Pinto wrote:
>> 
>> interface Gun { void fire(); }
>> interface Rocket { void fire(); }
>> 
>> class Weapon : Gun, Rocket { void fire() {} }
>> 
>> void protectMyself(Gun g) {
>>    g.fire(); // what did I actually do here?
>> }
>> 
>> void defence(Weapon w) {
>>    protectMyself(w);
>> }
>> 
>> The name might be merged, but semantics aren't the same and sometimes the unexpected happens, that is why Eiffel and .NET languages approach to explicitly state the interface implementations are much better.
>
> I would say that this design, at least in the example you proposed, is a bit backwards? I think the following looks better:

I always hear arguments like this, or something like "I personally never used such language feature and I don't think it should be used like in this scenario ..."

In that line of argument (of blaming user for mis-use), C++ could also be a perfect language: you as a user just need to use it in the "right" way. (well, as to the definition of "right", who knows).

I think the point is: we are talking about language feature here. If the language provide a feature, then it should anticipate the user will *abuse* it, and still being correct.

It's the compiler's job to disallow illegal usage: as long as it's not marked by the compiler as illegal, the language should give programmers freedom to *abuse* any language features, and the compiled program still being correct.

This is the case of Eiffel's multiple inheritance (MI). As a side notes: as mentioned, it's a pure OO language, there are occations OO inheritance hierarchy doesn't not make sense conceptually at all, and MI was used there just to bring in some needed functionalities/utilities, you can call that is abusing MI; BUT the compiled program always behave the correct semantics the user wanted. That's a huge achievement. They've set bar so high, I hope and encourage any language designer try to meet this bar as close as possible: (let me repeat)

"""
It's the compiler's job to disallow illegal usage: as long as it's not marked by the compiler as illegal, the language should give programmers freedom to *abuse* any language features, and the compiled program still being correct.

Do NOT blame the user for mis-usage / abuse, as long as executable generated, blame the compiler.
"""

> That said, this of course doesn't mean that there are cases where a function with the same name might be defined in two interfaces with different semantics:
>
> ```
> interface I1 {
>     int fun () out (r; r < 0);
> }
>
> interface I2 {
>     int fun () out (r; r > 0);
> }
>
> class C : I1,I2 {
>     int fun () {return /* ??? */;}
> }
> ```

Actually, this is a good example of how design-by-contract also need Eiffel-style MI's naming resolution technique, otherwise, you can not even make design-by-contract right.

> Of course, the fact that functions with the same name have different usage is also a bit suspicious, because interfaces

As just said, the user should never be blamed or feel sorry for this. It's the language that should detect such problem and also provide mechanism to allow user resolve the problem.

> should be orthogonal to each other, so I'm not too unhappy that it makes you think twice about it.

1 2 3 4 5 6 7 8 9
Next ›   Last »