гетери и сетери за суперкласове?

Все още ли е стандартна практика да се предоставят гетери и сетери в суперкласа, за подкласове за достъп до атрибутите на суперкласа (с други думи, задаване на атрибутите като частни)? Или атрибутите трябва да бъдат достъпни директно (обявявайки атрибутите като защитени) от подкласовете?

Има ли стандартна конвенция?


person user997112    schedule 22.02.2012    source източник
comment
На какъв език? C# и Java имат различни налични конструкции за излагане на стойности, което може да повлияе на това как бихте направили това на двата езика.   -  person KeithS    schedule 22.02.2012
comment
Дубликат: stackoverflow.com/questions/2279662/   -  person Robert Harvey    schedule 22.02.2012
comment
и stackoverflow.com/questions/3525765   -  person Robert Harvey    schedule 22.02.2012


Отговори (6)


Зависи изцяло от това, което искате да постигнете.

Ако искате атрибутите на суперкласа да бъдат достъпни, без да се наследяват, тогава трябва да декларирате публични гетери и сетери.

Ако, от друга страна, искате членовете да бъдат достъпни само ако суперкласът е наследен, тогава трябва да декларирате защитени членове.

Ако искате някаква форма на валидиране, имате нужда от гетери и сетери. Това предпазва суперкласа от непреднамерена корупция, дори ако е наследен.

person Robert Harvey    schedule 22.02.2012

Когато бях в университета и получавах диплома по CS, ни казаха да не правим геттери и сетери през втората година и да ги правим през петата година.

Моето лично предпочитание е да използвам гетери и сетери само там, където е абсолютно необходимо и никога да нямам публични променливи.

person christophmccann    schedule 22.02.2012

Вижте първите два отговора на този въпрос:

Геттерите и сетерите лош дизайн ли са? Виждат се противоречиви съвети

Не е чудесен отговор на въпроса ви, но вие очевидно сте загрижени за кодирането на добро OO, така че трябва да им помислите малко.

person Bill K    schedule 22.02.2012

В Java предпочитам да направя всичките си полета лични. Ако наистина трябва да изложа нещо, създавам отделен, защитен гетер за полето. (Например, ако интерфейсът, който прилагам, изисква по-широк тип връщане от това, което искам да предам между различните нива на реализации.)

С инструменти, които могат да генерират гетери/сетери с едно щракване на мишката, никога не съм почувствал необходимост да прекъсвам капсулирането дори между родителски/дете класове.

person biziclop    schedule 22.02.2012

Говорейки от страна на C#, ако имате член с данни (поле или свойство), който не е публичен, но е полезен за дъщерни класове и трябва да бъде достъпен както за четене, така и за писане, тогава декларирайте този член като защитен.

Ако членът трябва да бъде прочетен от подкласове, но не и написан, можете да дефинирате члена като собственост, която е защитена, но с частен сетер:

//as of C# 3.0 this can also be an auto-property
private string myValue;
protected string MyValue 
{
   get{return myValue;} 
   private set{myValue = value;}
}

Това прави MyValue напълно скрит за класове извън йерархията на наследяване и само за четене за подкласове; само самият суперклас може да зададе стойността. Това би било еквивалентно на частно поле със защитен метод за получаване и частен метод за настройка.

Като цяло, като дизайнер на суперкласа, от вас зависи да определите как подкласовете трябва да могат да използват това, което предоставяте. Ако направите нещо защитено, приемете, че подкласовете ще направят всичко, което „защитените“ им позволяват. И C#, и Java имат методи, чрез които можете независимо да контролирате видимостта на достъпа за четене и запис.

person KeithS    schedule 22.02.2012

Изглежда, че в C# стандартната практика е да се използват свойства с инструменти за достъп get/set. В опростената форма ще имате:

public string Name { get; set; }

Но може да имате по-фин контрол върху нивото на достъп, например:

public string Name { get; protected set; }

Тук излагате публично метода get, но оставяте метода set само на производни класове.

Друго предимство от използването на инструменти за достъп вместо директен достъп до член на данни е, че можете да поставите точка на прекъсване на метод get/set и да видите кой е изпълнил метода.
Това обаче не е възможно с трика { get; set; }. Ще трябва да напишете целия разширен формуляр за собственост:

private string m_Name = string.Empty;
public string Name
{
    get { return m_Name; }  // Put a happy breakpoint here
    set { m_Name = value; } // or here.
}

Ще бъде безопасно да се отрази същата концепция за Java.

person AVIDeveloper    schedule 22.02.2012