Это очень разные языки, особенно в этой области. Допустим, у вас есть класс. В этом случае мы сделаем это пользовательским элементом управления, что-то вроде текстового поля. Назовите это UIControl. Теперь мы хотим поместить это в другой класс. В этом случае, поскольку мы используем пользовательский интерфейс для нашего примера, мы назовем его классом CleverPanel. Наш экземпляр CleverPanel захочет узнать о том, что происходит с его экземпляром UIControl по разным причинам. Как это сделать?
В C # основной подход заключается в проверке различных событий, настройке методов, которые будут выполняться при запуске каждого интересного события. В Java, в которой отсутствуют события, обычным решением является передача объекта с различными методами обработки «события» в метод UIControl:
boolean stillNeedIt = ... ;
uiControl.whenSomethingHappens( new DoSomething() {
public void resized( Rectangle r ) { ... }
public boolean canICloseNow() { return !stillNeedIt; }
public void closed() { ... }
...
} );
Пока что разница между C # и Java невелика. Однако у нас есть интерфейс DoSomething, который не нужен в C #. Кроме того, этот интерфейс может включать в себя множество методов, которые не нужны большую часть времени. В C # мы просто не обрабатываем это событие. В Java мы создаем класс, который обеспечивает нулевую реализацию для всех методов интерфейса, DoSomethingAdapter. Теперь мы заменяем DoSomething на DoSomethingAdapter, и нам вообще не нужно писать никаких методов для чистой компиляции. В итоге мы просто переопределяем методы, необходимые для правильной работы программы. Таким образом, в итоге нам нужен интерфейс и использование наследования в Java, чтобы соответствовать тому, что мы делали с событиями в C #.
Это пример, а не всестороннее обсуждение, но он дает основы того, почему в Java так много наследования, в отличие от C #.
Теперь, почему Java работает таким образом? Гибкость. Объект, переданный на whenSomethingHappens, мог быть полностью передан CleverPanel из другого места. Это может быть что-то, что несколько экземпляров CleverPanel должны передать своим UIControl-подобным объектам, чтобы помочь объекту CleverWindow где-нибудь. Или UIControl может передать его одному из своих компонентов.
Кроме того, вместо адаптера может быть где-то реализация DoSomething, за которой стоят тысячи строк кода. Мы могли бы создать новый экземпляр этого и передать его. Возможно, нам придется переопределить один метод. Обычная хитрость в Java - иметь большой класс с таким методом:
public class BigClass implements DoSomething {
...many long methods...
protected int getDiameter() { return 5; }
}
Затем в CleverlPanel:
uiControl.whenSomethingHappens( new BigClass() {
@Override
public int getDiameter() { return UIPanel.currentDiameter; }
} );
Платформа Java с открытым исходным кодом делает многое из этого, что побуждает программистов делать больше - и потому, что они следуют этому в качестве примера, и просто для того, чтобы использовать его. Я действительно думаю, что базовый дизайн языка лежит в основе разработки фреймворка Sun и позади использования Java-программистом техник, когда фреймворк не используется.
Создать класс на лету очень просто. На класс, анонимный или именованный, нужно ссылаться только в одном небольшом блоке кода, скрытом глубоко в одном методе. Он может быть создан совершенно новым или путем небольших модификаций очень большого существующего класса. (И существующий класс может быть верхнего уровня в своем собственном файле, или вложенным в класс верхнего уровня, или определяться только в пределах одного блока кода). Новый экземпляр класса может иметь полный доступ ко всем данным создаваемого объекта. И новый экземпляр можно передать и использовать по всей программе, представляя объект, который его создал.
(Кроме того, обратите внимание, что широкое использование наследования здесь - как и в других местах в Java - просто для целей СУХОЙ. Это позволяет различным классам повторно использовать один и тот же код. Обратите внимание также на простоту наследования в Java, которая поощряет это. )
Опять же, это не всестороннее обсуждение; Я просто царапаю поверхность здесь. Но да, есть удивительная разница в том, как наследование используется между Java и C #. В этом отношении они очень разные языки. Это не ваше воображение.