Чи поганий підхід сам метод передачі (цей) до методу поля?

Я програмую невелику гру, і у мене два класи: Board і Piece . Board має (поки) один Piece , який можна перемістити в межах Board .

public class Board {
  private Piece piece_;
  private int width, height;
  ...

  movePieceDown() {
    piece_.moveTo(this, 1, 2);
  }
}

public class Piece {
  public boolean moveTo(Board board, int x, int y) {
   //move piece to new location (x,y)
   //return true if successful
  }
}

Чи є поганий підхід, якщо я в piece_.moveTo (this, 1, 2); передаю посилання на Board, щоб Piece міг перейти на нове місце, якщо на борту немає перешкод? Не проходячи посилання на правління, Piece не знає, чи є перешкоди на новому місці, або це не з меж правління.

Це на мій погляд, що кожен об'єкт повинен турбуватися тільки про себе: шматок повинен перейти на нове місце, і рада повинна турбуватися, якщо це законний хід чи ні, але цей приклад коду я написав більше сенсу і спрощує речі.

TL; DR: Чи порушую деякі рекомендації ООП з передачею самого об'єкта до методу поля або це звичайна ідіома ООП? Заздалегідь спасибі за пояснення цього.

5
Чому ви передаєте Board для переміщенняPieceDown?
додано Автор Joachim Isaksson, джерело
Так, хороший виклик, вибачте, що це була помилка, коли я вибирала код для розміщення. Тепер буде змінено.
додано Автор h00s, джерело

7 Відповіді

Це не поганий підхід. Передача цього різним методам не є рідкістю в програмуванні. Це залежить тільки від вашого дизайну і, наскільки мені це цікаво, нічого в класі Piece .

У класі Board можна заплутати - метод movePieceDown . У вас є непридатний параметр Board board . Якщо ви плануєте використовувати this як аргумент, видаліть цей атрибут, оскільки плата не повинна отримувати інші плати як потенційні аргументи, і, по суті, не слід знати, що інші плати можуть існувати.

І, нарешті, можна переконатися, що Piece бачить інтерфейс Board як параметр методу, і переконайтеся, що цей контракт ніколи не зміниться. Наприклад, він може мати такі способи:

public interface IBoard { 
    public boolean isFieldFree(int x, int y)
    public Piece getPiece(int x, int y) 
}

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

8
додано
Раді допомогти. Не на cemu. :)
додано Автор darijan, джерело
Дякуємо за вашу відповідь darijan, і вітання з Хорватії :). Так, це була друкарська помилка в моєму зразку коду, не повинна була бути там, хороший виклик.
додано Автор h00s, джерело

По-перше, чому ваша змінна фрагмента закінчується підкресленням? Це просто дивно: p

А що стосується вашого питання. Я б обробляв всі штучні речі, такі як переміщення в класі. Якщо ви хочете знати, на якій позиції на борту ви перебуваєте, я б мав 2 цілих змінних у вашому класі шматок називається x і y.

Частина не повинна знати, якщо вона зіткнеться з деякою іншою частиною на дошці, тому що це те, що ваш клас дошки повинен обробляти при переміщенні частини.

Так, наприклад, якщо ви переміщуєте свій шматок в x = 1 і y = 2, ви повинні мати вашу плату, щоб перевірити, чи вже є частина в позиції 1,2 і відповідати відповідним чином.

Немає нічого поганого в тому, щоб передати "це" в метод іншого класу, але з точки зору вільно пов'язаного об'єктно-орієнтованого програмування це не є оптимальним дизайном.

Тільки мої 2 центи :)

3
додано
@ h00s використовувати підкреслення в цих випадках називається поганим стилем від Sun. Я знаю, що оракул перейняв, але це архаїчно, і його слід уникати, якщо це можливо. Ваша висота і ширина також є приватними, але не закінчуються підкресленням, до речі :)
додано Автор JREN, джерело
Використання this.color = color краще, ніж color_ = color yes. Ви можете знайти узгодження назв java тут:
додано Автор JREN, джерело
Усі мої приватні поля закінчуються символом підкреслення :) Це дозволяє легко розрізняти змінні класу з локальних змінних scratch, як вказано в рекомендаціях щодо стилю Java-стилів - = "nofollow noreferrer"> посилання Дякуємо за 2 центів :)
додано Автор h00s, джерело
Людина, ви дійсно не можете пропустити нічого;) Підкреслення робить для мене такі речі, як конструктори public Piece (Колірний колір) {color_ = color; } більш чітко. Чи повинен я відкинути це на користь Public Piece (колір кольору) {this.color = колір; } ? Або, що ще краще, чи є більш свіжі керівні принципи Java, які я можу шукати? Дякую!
додано Автор h00s, джерело

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

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

2
додано

Як правило, передача цього не є рідкістю, але це залежить від випадку. У цьому випадку бог залежить від деталей реалізації. Дошка має кілька трубок, які можуть переміщатися, тому позиція є властивістю частини. Проте переміщення фрагмента з одного місця в інше може бути функцією плати. Що відбувається, наприклад, якщо нове місце вже зайнято? Чи буде шматок потім перемістити інші частини навколо? Чи буде це підходящим для вашого дизайну?

З вашого підпису на шматку, я б очікував, що функція moveTo приймає дошку, що вказує мені, що шматок може переходити з однієї дошки на іншу. При читанні коду це може бути пропущеним, якщо це не так.

2
додано

Відповісти саме на конкретне питання в заголовку (а не на загальні думки про дизайн ОО): Ні, це не погана практика, а досить поширена.

Однак пам'ятайте, що передача цього у зовнішній світ у конструкторі не рекомендується, оскільки це може призвести до неприємних помилок у паралельному сценарії, де приймач може бачити джерело в невідповідному стані.

1
додано

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

Об'єктно-орієнтоване програмування багато в чому полягає в тому, щоб бачити речі, як якщо б вони були об'єктами в реальному світі. Слідуючи такому підходу, я б дивився на неї, як ніби шматок знаходиться на дошці, і, наприклад, його позиція визначається радою, а не сама по собі. З цього підходу, то переміщення шматка щось робиться на дошці, а не сам шматок.

Отже, незважаючи на те, що не правильно передавати this як параметр, я б скоріше визначив метод:

public class Board
{
    private Piece p;
   //...

    public boolean movePieceDown()
    {
       //Move the piece to a new location using it's setters
    }
}

Окрім цього, оскільки об'єкт Board знає про його атрибути, результуючий код буде набагато більш читабельним, тому що вам не доведеться викликати стільки геттерів і сеттерів (для перевірки меж) наприклад).

1
додано

це неявно передається з нормальним викликом методу. Прочитайте цей відповідь , який я знайшов на форумі.

Ви також можете прочитати специфікацію JVM для цього.

0
додано
ІТ КПІ - Java
ІТ КПІ - Java
436 учасників