@linesb

В каких случаях использовать приватные поля при определении класса?

Есть мнение что когда пишется класс нужно большинство свойств сделать приватными, чтобы никто не мог менять внутреннее состояние обектов уменшив таким образом непредсказуемые ситуации. Другие обясняют что состояние объекта это дела объекта (он сам решает как менять). А чтобы влиять на объект можем вызывать его публичные методы, а он изменит (если нужно) состояние.

Но если делать все приватное то у нас не бдет доступа не только на изменение но и на чтение, а это часто нужно. В связи с этим у меня и появился вопрос как быть в такой ситуацией: делать getter-ы (на всех или только некоторые своиства), делать методы которые бы использовали приватные своиства, или делать публичными и оставить ответственность правильного изменения на програмиста?

Пример: есть прямоугольник (Rectangle) которого хотим рисовать на каким нибудь полотном (Canvas)
class Rectangle {
	private x, y, w, h: number;

	constructor(x, y, w, h: number) {
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h;
	}

	// ......
}

class Canvas {
	private w, h: number;

	constructor(w, h: number) {
		this.w = w;
		this.h = h;
	}	

	public drawRect(rect: Rectangle) {
		// Здесь нужны координать и размеры прямоуголника
	}
}

const rect = new Rect(0, 0, 10, 15);
const canvas = new Canvas(20, 40);
canvas.drawRect(rect);


В методе drawRect нужны координать и размеры прямоугольника, стоит ли их делать публичными или делать getter-ы для всех этих свойств?

Или может в метод drawRect стойт передовать x, y, w, h и делать еще и метод draw на прямоугольнике

class Rectangle {
	private x, y, w, h: number;

	constructor(x, y, w, h: number) {
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h;
	}

	public drawOnCanvas(canvas: Canvas) {
		canvas.drawRect(x, y, w, h);
	}
}

class Canvas {
	private w, h: number;

	constructor(w, h: number) {
		this.w = w;
		this.h = h;
	}	

	public drawRect(x, y, w, h: number) {
		// Есть все что нужно для рисования !!!!
	}
}

const rect = new Rect(0, 0, 10, 15);
const canvas = new Canvas(20, 40);
rect.drawOnCanvas(canvas);


Ну или все делать публично и использовать то что нужно и когда нужно?
  • Вопрос задан
  • 288 просмотров
Пригласить эксперта
Ответы на вопрос 3
sarapinit
@sarapinit
Точу водой камень
если у вас typescript, вы можете так сделать

class Rectangle {
  readonly x: number
  readonly y: number
  readonly w: number
  readonly h: number
    
  constructor(x: number, y: number, w: number, h: number) {
    this.x = x
    this.y = y
    this.w = w
    this.h = h
  }
}

class Canvas {
  private w: number
  private h: number

  constructor(w: number, h: number) {
    this.w = w;
    this.h = h;
  }	

  public drawRect(rect: Rectangle) {
    //draw implementation
  }
}


В этом случае Rectangle просто контейнер для чисел и никто его менять не может. Но поля публичные и то позволяет его отрисовать.
Но это решение справедливо только для этого случая. В целом вопрос более глубокий и не имеет единого ответа.

Рекомендую почитать про Rich model и Anaemic model, это даст некоторое понимание про разницу подходов и то какие плюсы\минусы есть.
Ответ написан
HemulGM
@HemulGM
Delphi Developer, сис. админ
Вы здесь почти ничего осмысленного из ООП не используете. Пишу пример на паскале, но это ничего не меняет.

Стандартным решением было бы создать базовый класс "Рисуемый", тот, который может быть отрисован на канве.
Допустим TSprite. И объявим виртуальный метод Draw, чтобы мы могли попросить отрисываться.
TSprite = class //ну или интерфейс
public
  procedure Draw; virtual; abstract;
end;

Теперь напишем класс TRectangle на основе класса TSprite. Где тоже объявим метод Draw, но напишем там уже отрисовку. Ну и объявим приватные поля размеров и позиции с конструктором.
TRectangle = class(TSprite)
private
  FX, FY, FH, FW: Float;
  FCanvas: TCanvas;
public
  procedure Draw; override;
  constructor Create(Canvas: TCanvas; const X, Y, H, W: Float); 
end;

constructor TRectangle.Create(Canvas: TCanvas; const X, Y, H, W: Float); 
begin
  FCanvas := Canvas;
  FX := X;
  FY := Y;
  FH := H;
  FW := W;
end;

procedure TRectangle.Draw;
begin
  FCanvas.Rectangle(FX, FY, FH, FW); // Это отрисовка фигуры на канве
end;


Теперь мы можем создавать класс TRectangle, указывать целевую канву и размеры.
Rect := TRectangle.Create(Canvas, 10, 10, 40, 45);
Rect.Draw; // Всё, можно отрисовать


После всего этого мы можем создать другие фигуры или объекты, которые тоже будут наследоваться от TSprite. Сможем поместить их в список объектов типа TSprite и обращаться к каждому объекту через Draw. Например, в цикле отрисовки всех объектов.
Ответ написан
firedragon
@firedragon
Не джун-мидл-сеньор, а трус-балбес-бывалый.
В примитивных классах как раз поля и должны быть публичными. Что бы меньше лапши было. Но это не относится к презентации. Тотесть у вас есть прямоугольник и хранимый в базе прямоугольник. В первом случае через поля, во втором только через метод который и в базу сохраняет и после меняет поля
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы