Здравствуйте, nikov, Вы писали:
N>Объясните, пожалуйста, почему такая декларация интерфейса недопустима:
Вообще-то компилятор довольно популярно объясняет причину.
N>Если можно, то со ссылкой на спецификацию языка.
На что спеку-то? На то что нельзя переопределять final методы? Или на то что нельзя делать перегрузку метода с изменением только return типа?
Здравствуйте, Blazkowicz, Вы писали:
B>На что спеку-то? На то что нельзя переопределять final методы? Или на то что нельзя делать перегрузку метода с изменением только return типа?
Во-первых, для меня неочевидно, что здесь я пытаюсь переопределять final метод. Например, в C# аналогичный код вполне бы проканал. Поэтому и прошу объяснение из спецификации.
Здравствуйте, nikov, Вы писали:
N>Здравствуйте, Blazkowicz, Вы писали:
B>>На что спеку-то? На то что нельзя переопределять final методы? Или на то что нельзя делать перегрузку метода с изменением только return типа?
N>Во-первых, для меня неочевидно, что здесь я пытаюсь переопределять final метод. Например, в C# аналогичный код вполне бы проканал. Поэтому и прошу объяснение из спецификации.
Так как в яве все инстанс методы виртуальные, то значит перекрываешь.
для перекрытия нет специального синтаксиса поэтому его не отличить от определения.
а нет его потому что кроме перекрытия ничего сделать нельзя
9.4.2 Overloading
If two methods of an interface (whether both declared in the same interface, or both inherited by an interface, or one declared and one inherited) have the same name but different signatures that are not override-equivalent (§8.4.2), then the method name is said to be overloaded. This fact causes no difficulty and never of itself results in a compile-time error. There is no required relationship between the return types or between the throws clauses of two methods with the same name but different signatures that are not override-equivalent.
То есть return type не определяет сигнатуру метода.
The signature of a method consists of the name of the method and the number and types of formal parameters to the method. A class may not declare two methods with the same signature, or a compile-time error occurs.
Т.о. методы различающиеся лишь возвращаемым типом имеют одинаковую сигнатуру.
Здравствуйте, nikov, Вы писали:
N>Во-первых, для меня неочевидно, что здесь я пытаюсь переопределять final метод. Например, в C# аналогичный код вполне бы проканал. Поэтому и прошу объяснение из спецификации.
Так оно неочевидно именно из-за того, что джава != c#. Т.е. в джаве невозможно создать non-private неполиморфный инстанс-метод, который можно было бы переопределить в потомке. Опять же в c# нет возможности явно запретить переопределение метода ('final' в сигнатуре метода).
...
* If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface. It is a compile-time error if the interface explicitly declares such a method m in the case where m is declared to be final in Object.
Здравствуйте, nikov, Вы писали:
N>Во-первых, для меня неочевидно, что здесь я пытаюсь переопределять final метод. Например, в C# аналогичный код вполне бы проканал. Поэтому и прошу объяснение из спецификации. flood mode on
это, чтобы дотнетчикам жизнь мёдом не казалась flood mode off
B>All class and array types inherit the methods of class Object, which are summarized here
Но в данном случае у меня не класс или массив, а интерфейс.
B>Т.о. методы различающиеся лишь возвращаемым типом имеют одинаковую сигнатуру.
Согласен, сигнатуры совпадают. Но почему должна быть ошибка компиляции?
Здравствуйте, denis.zhdanov, Вы писали:
DZ>Т.е. в джаве невозможно создать non-private неполиморфный инстанс-метод, который можно было бы переопределить в потомке.
В C# тоже невозможно создать неполиморфный метод, который можно было бы переопределить в потомке.
DZ>Опять же в c# нет возможности явно запретить переопределение метода ('final' в сигнатуре метода).
Там для этой цели есть модификатор метода sealed.
DZ>
DZ>...
DZ>* If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface. It is a compile-time error if the interface explicitly declares such a method m in the case where m is declared to be final in Object.
Получается, интерфейс неявно определяет публичный абстрактный метод getClass с такой же сигнатурой и типом возвращаемого значения, как метод getClass в классе Object. А явно определяет метод getClass с другим типом возвращаемого значения. Ошибка-то отчего?
Здравствуйте, nikov, Вы писали:
N>Но в данном случае у меня не класс или массив, а интерфейс.
Любой интерфейс подразумевает что его будет реализовывать какой-либо класс. Любой класс унаследован от Object. Даже если это Proxy!
B>>Т.о. методы различающиеся лишь возвращаемым типом имеют одинаковую сигнатуру. N>Согласен, сигнатуры совпадают. Но почему должна быть ошибка компиляции?
Сигнатура совпадает, следовательно, это не overload. Значит override, а override не возможен, т.к. переопределяемый метод — final. Лучше расскажи почему ты считаешь что это всё не логично.
Здравствуйте, nikov, Вы писали:
N>В C# тоже невозможно создать неполиморфный метод, который можно было бы переопределить в потомке.
using System;
namespace Polymorphism
{
class A
{
public void Foo() { Console.WriteLine("A::Foo()"); }
}
class B : A
{
public void Foo() { Console.WriteLine("B::Foo()"); }
}
class Test
{
static void Main(string[] args)
{
A a;
B b;
a = new A();
b = new B();
a.Foo(); // output --> "A::Foo()"
b.Foo(); // output --> "B::Foo()"
a = new B();
a.Foo(); // output --> "A::Foo()"
}
}
}
N>Там для этой цели есть модификатор метода sealed.
Он не может быть применен к методу. Но вообще да, я про него забыл.
...
* If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface. It is a compile-time error if the interface explicitly declares such a method m in the case where m is declared to be final in Object.
N>Получается, интерфейс неявно определяет публичный абстрактный метод getClass с такой же сигнатурой и типом возвращаемого значения, как метод getClass в классе Object. А явно определяет метод getClass с другим типом возвращаемого значения. Ошибка-то отчего?
Из-за того, что в джаве не разрешено иметь перегруженные методы отличающиеся только типом возвращаемого значения.
Cyberax wrote:
> Empty empty=new Empty() {};
Это нечестно. Тут неявно определяется анонимный класс, реализующий данный интерфейс. Точнее надо "Empty.class"
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ., Вы писали:
>> Empty empty=new Empty() {}; .>Это нечестно. Тут неявно определяется анонимный класс, реализующий данный интерфейс. Точнее надо "Empty.class"
Empty.class — ничего не означает.
Class clazz=int.class;
assert clazz.getDeclaredMethods().length==0; //Всё ОК!
Cyberax wrote:
>> > Empty empty=new Empty() {}; > .>Это нечестно. Тут неявно определяется анонимный класс, реализующий > данный интерфейс. Точнее надо "Empty.class" > Empty.class — ничего не означает.
Т.е.? Не понял. ".class" — тупо обращение к публичному статическому финальному полю.
public class Test
{
interface Empty{}
public static void main(String []args)
{
System.out.println(Empty.class);
System.out.println(new Empty(){}.getClass());
System.out.println(int.class);
}
}
работает вполне очевидно.
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ., Вы писали:
.>Т.е.? Не понял. ".class" — тупо обращение к публичному статическому финальному полю.
Нет, .class — это специальная конструкция языка. Она работает и для примитивов, хотя никаких полей у них нет.
Здравствуйте, Blazkowicz, Вы писали:
B>>>Т.о. методы различающиеся лишь возвращаемым типом имеют одинаковую сигнатуру. N>>Согласен, сигнатуры совпадают. Но почему должна быть ошибка компиляции? B>Сигнатура совпадает, следовательно, это не overload. Значит override, а override не возможен, т.к. переопределяемый метод — final. Лучше расскажи почему ты считаешь что это всё не логично.
Я вовсе не считаю, что это нелогично. Просто я в отпуске и решил разобраться со спецификацией языка Java. Вижу, что многие вещи отличаются от C#, но пока не могу найти достаточно понятных объяснений. Был бы признателен, если бы ты не просто объяснил это своими словами, а сказал, где именно это в спецификации написано.
Кроме того, я не могу применить твое объяснение к такой ситуации:
public class A {
private final void foo() { }
public class B extends A {
public void foo() { } // а это что: overload или override?
}
}
Здравствуйте, nikov, Вы писали:
N>Кроме того, я не могу применить твое объяснение к такой ситуации: N>
N>public class A {
N> private final void foo() { }
N> public class B extends A {
N> public void foo() { } // а это что: overload или override?
N> }
N>}
N>
Это ни overload, ни override. Приватные просто методы никак не влияют на наследуемые классы.
Здравствуйте, denis.zhdanov, Вы писали:
N>>В C# тоже невозможно создать неполиморфный метод, который можно было бы переопределить в потомке.
DZ>
DZ> using System;
DZ> namespace Polymorphism
DZ> {
DZ> class A
DZ> {
DZ> public void Foo() { Console.WriteLine("A::Foo()"); }
DZ> }
DZ> class B : A
DZ> {
DZ> public void Foo() { Console.WriteLine("B::Foo()"); }
DZ> }
DZ>
Здесь метод потомка не переопределяет, а скрывает метод базового класса.
N>>Там для этой цели есть модификатор метода sealed. DZ>Он не может быть применен к методу. Но вообще да, я про него забыл.
Еще как может. Попробуй:
class A {
public override sealed string ToString() { return"A"; }
}
DZ>
DZ>...
DZ>* If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface. It is a compile-time error if the interface explicitly declares such a method m in the case where m is declared to be final in Object.
N>>Получается, интерфейс неявно определяет публичный абстрактный метод getClass с такой же сигнатурой и типом возвращаемого значения, как метод getClass в классе Object. А явно определяет метод getClass с другим типом возвращаемого значения. Ошибка-то отчего?
DZ>Из-за того, что в джаве не разрешено иметь перегруженные методы отличающиеся только типом возвращаемого значения.
Я не вижу, где такое написано — "не разрешено". Вижу только, что методы интерфейса называются перегруженными, когда они имеют одинаковые имена, но разные сигнатуры.