Чи розробка Java зазвичай передбачає більше підкласингу, ніж C # /. NET?


34

Нещодавно я почав дивитися на розробку Android. Це повернуло мене у світ розробки програмного забезпечення Java. Останній раз, коли я працював з Java, зізнаюся, я не зрозумів OOP майже так само, як (я думаю) зараз.

В основному використовуючи C # у своїй кар'єрі, я помічаю приголомшливу різницю в тому, як в спадщині використовуються Java та C #.

У C # здавалося, що спадщини можна уникнути у більшості ситуацій. Задача, яку можна знайти, зазвичай може бути виконана за допомогою конкретних класів рамки .NET .

У Java з того, що я збираю з зразків коду, здається, що рамка Java постачає багато інтерфейсів або абстрактних класів, які потім призначені для впровадження / розширення розробником.

Здається, це занадто велика різниця, щоб просто звести до стилю. Які міркування за цим? Я відчуваю, що не буду писати чистий код Java, поки не зрозумію цього.

Крім того, чи обмежено це лише SDK для Android або це підхід до OOP у загальному для Java?

Або по-іншому,

Що стосується дизайну цих двох мов, які (схоже, заохочують) використання більш успадкованого використання, ніж інші?

Якщо мови трактують успадкування однаково, і якщо вважати, що моє спостереження є дійсним, то це означає, що це пов'язано з дизайном рам / бібліотек, а не з мовами. Якою мотивацією буде такий вид дизайну?


1
Це правда. У Java занадто багато інтерфейсів. Мені б хотілося знати, чому така поведінка розробників є загальною для конкретної мови. Я бачу, що це відбувається частіше в проектах Java, ніж будь-який інший. Має бути причина цього, а не лише думка.
Реакційний

1
@MathewFoscarini - це лише твоя думка . У Java-проектах, в яких я брав участь, розробники схилялися уникати спадкування, як чума. Тут нічого авторитетного, лише моя думка . Хочете опитування ?
гнат

2
Вам, майже, ніколи не потрібно виводити один клас з іншого на Java. Натомість ви можете реалізувати інтерфейси для досягнення поліморфізму та реалізувати складені об'єкти та проксі, за допомогою яких метод вимагає досягти спільної функціональності.
DwB

1
@ThinkingMedia Загалом, Java переповнена зусиллями / пуристами ОСС. Академічні принципи є головним питанням. .Net розробники - це прагматики, які турбуються про те, щоб виконати роботу. Вони цінують робочий код більше, ніж найчистіший код.
Енді

Відповіді:


31

Здається, це занадто велика різниця, щоб просто звести до стилю. Які міркування за цим?

Я розумію, що це багато в чому просто стилістичне рішення. Ну, можливо, не стиль, а ідіоми мови / середовища. Розробники стандартної бібліотеки Java дотримувались одного набору керівних принципів дизайну, а розробників .NET - іншого (хоча вони мали можливість бачити, як працює підхід Java).

Справжніх мов дуже мало, щоб заохотити або відмовити від спадщини. Лише дві речі вражають мене як відповідні:

  1. .NET впроваджував дженерики раніше за своє життя, до того, як було запроваджено занадто багато негенеричного коду. Альтернатива - це багато спадщини для набору речей, що спеціалізуються.

  2. Більшою зміною було те, що .NET підтримував делегатів. У Java вам застрягло (анонімне) успадкування, щоб забезпечити найосновніші функції змінної функції. Це призводить до відносно великої різниці в тому, як код створений для того, щоб або скористатися перевагами делегатів, або уникнути незручних структур успадкування, необхідних для цього на Java.


3
Я думаю, що ця відповідь пропонує дуже правдоподібне пояснення. Особливо справа про анонімне успадкування на місці делегатів. Я багато цього спостерігав. Спасибі.
MetaFight

3
Не забувайте анонімні типи та дерева синтаксису / вирази лямбда, які були введені в .NET 3.5. І звичайно, вибирайте динамічне введення в .NET 4. Зараз це майже безперечно мова змішаної парадигми, не суто об'єктно-орієнтована.
Aaronaught

так, на моєму досвіді, використовуючи обидва (в тому числі для змішаних проектів, де ті самі люди використовують обидві мови) люди, як правило, вважають за краще використовувати більшу кількість менших класів при кодуванні Java, меншу кількість більших класів (тенденція до класів богів), коли за допомогою C #. Навмисно прототипуючи одне і те ж, використовуючи один і той же стиль в обох, ви отримуєте аналогічну кількість класів (використовуючи часткові класи, ви, швидше за все, отримаєте більше файлів коду, навіть коли використовуєте C #).
jwenting

6

Це дуже різні мови, особливо в цій галузі. Скажімо, у вас клас. У цьому випадку ми зробимо його керуванням користувачем, чимось на зразок текстового поля. Назвіть це 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 працює таким чином? Гнучкість. Об'єкт передається, колиSomethingHappens міг би бути переданий 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 та C #. У цьому відношенні вони дуже різні мови. Це не ваша уява.


Примітка. Ви можете уникнути необхідності надавати методи, які нічого не роблять, розширивши абстрактний клас, повний порожніх реалізацій. Таким чином можна вибірково перекрити методи, які щось роблять. Хоча це не так потворно, це означає інший рівень успадкування.
Пітер Лорі

-2

Існує абсолютно ніяка різниця в тому, як обробляти спадщину між Java та C #. Коли ви насправді будете використовувати спадщину чи композицію, це, безумовно, дизайнерське рішення, і жодним чином це не те, що Java або C # заохочує або відштовхує. Я б радив прочитати цю статтю .

Сподіваюся, я допоміг!


5
Ви говорите про самі мови, але, думаю, питання стосується також бібліотек та загального користування.
svick

3
Але в іншій мові є примхи, які заохочують додаткове успадкування на Java; дивіться відповідь
РальфаЧепіна
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.