Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #67849 > unrolled thread
| Started by | JiiPee <no@notvalid.com> |
|---|---|
| First post | 2019-08-21 20:22 +0100 |
| Last post | 2019-08-23 15:49 +0000 |
| Articles | 20 — 9 participants |
Back to article view | Back to comp.lang.c++
About getters/setters JiiPee <no@notvalid.com> - 2019-08-21 20:22 +0100
Re: About getters/setters Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-08-21 19:34 +0000
Re: About getters/setters Bo Persson <bo@bo-persson.se> - 2019-08-21 21:40 +0200
Re: About getters/setters Öö Tiib <ootiib@hot.ee> - 2019-08-21 12:52 -0700
Re: About getters/setters JiiPee <no@notvalid.com> - 2019-08-22 15:25 +0100
Re: About getters/setters Öö Tiib <ootiib@hot.ee> - 2019-08-22 09:06 -0700
Re: About getters/setters Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-08-24 04:32 -0700
Re: About getters/setters Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-08-22 15:09 -0700
Re: About getters/setters Ian Collins <ian-news@hotmail.com> - 2019-08-23 16:17 +1200
Re: About getters/setters Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-08-23 05:26 -0700
Re: About getters/setters Melzzzzz <Melzzzzz@zzzzz.com> - 2019-08-23 18:07 +0000
Re: About getters/setters JiiPee <no@notvalid.com> - 2019-08-23 07:09 +0100
Re: About getters/setters JiiPee <no@notvalid.com> - 2019-08-23 07:13 +0100
Re: About getters/setters David Brown <david.brown@hesbynett.no> - 2019-08-23 09:30 +0200
Re: About getters/setters Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-08-25 06:16 +0000
Re: About getters/setters David Brown <david.brown@hesbynett.no> - 2019-08-25 12:12 +0200
Re: About getters/setters Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-08-23 11:24 +0000
Re: About getters/setters James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-08-23 08:34 -0400
Re: About getters/setters Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-08-23 14:48 +0000
Re: About getters/setters Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-08-23 15:49 +0000
| From | JiiPee <no@notvalid.com> |
|---|---|
| Date | 2019-08-21 20:22 +0100 |
| Subject | About getters/setters |
| Message-ID | <kSg7F.32840$Xs5.970@fx06.am4> |
Which one is better:
1)
class Person
{
public:
int getAge() { return age;}
void setAge(int a) { age = a;}
private:
int age;
};
or
2)
struct Person
{
int age;
};
####
I know Herb Sutter recommended 1) but for example isocpp
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get
seems to recommend 2). Herb says that for example when debugging 1) is
good because you can write to file all the accesses of the age, or cout
all the calls. Also debugger can stop at the function call, but can
debugger stop at :
person.age = 6;
?
So debugger can put a red dot to setAge and see which object changed it.
And cout/write on file information.
Argument also, that later on can add other functionality punder setAge
(like cache logic).
But 2) people argue its so simple and not likely to change, so it breaks
OO idea.
I do currently 1) but wondering which way to go.
Like now I have a "Settings" class. Simple data members. I started
adding getters and setters....
[toc] | [next] | [standalone]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2019-08-21 19:34 +0000 |
| Message-ID | <slrnqlr75s.cdo.grahn+nntp@frailea.sa.invalid> |
| In reply to | #67849 |
On Wed, 2019-08-21, JiiPee wrote:
> Which one is better:
>
> 1)
>
> class Person
> {
> public:
> int getAge() { return age;}
There's a const missing.
> void setAge(int a) { age = a;}
>
> private:
> int age;
> };
>
> or
>
> 2)
>
> struct Person
> {
> int age;
> };
Or one which is not invalidated by time itself:
struct Person {
explicit Person(const Date& birthday);
const Date birthday;
};
(Ignoring intricacies of hours, minutes and time zones, and people of
unknown age.)
It depends on what you're modeling and how you want to model it.
Saying one is better than the other is like saying a spoon is better
than a fork.
/Jorgen
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
[toc] | [prev] | [next] | [standalone]
| From | Bo Persson <bo@bo-persson.se> |
|---|---|
| Date | 2019-08-21 21:40 +0200 |
| Message-ID | <gs5l26F48alU1@mid.individual.net> |
| In reply to | #67849 |
On 2019-08-21 at 21:22, JiiPee wrote:
> Which one is better:
>
> 1)
>
> class Person
>
> {
>
> public:
>
> int getAge() { return age;}
>
> void setAge(int a) { age = a;}
>
> private:
>
> int age;
>
> };
>
> or
>
> 2)
>
> struct Person
>
> {
>
> int age;
>
> };
>
> ####
>
> I know Herb Sutter recommended 1) but for example isocpp
>
> https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get
>
> seems to recommend 2). Herb says that for example when debugging 1) is
> good because you can write to file all the accesses of the age, or cout
> all the calls. Also debugger can stop at the function call, but can
> debugger stop at :
>
> person.age = 6;
>
> ?
>
> So debugger can put a red dot to setAge and see which object changed it.
> And cout/write on file information.
>
> Argument also, that later on can add other functionality punder setAge
> (like cache logic).
>
> But 2) people argue its so simple and not likely to change, so it breaks
> OO idea.
>
> I do currently 1) but wondering which way to go.
>
> Like now I have a "Settings" class. Simple data members. I started
> adding getters and setters....
>
There probably isn't a general answer, except that it depends.
If you model a real person, the age doesn't change except by +1 on each
birthday. So what is the use for setAge?
In the Core Guidelines you have a Point(x, y) where it is unclear what
the use for set_x is. So you could just skip it.
If the class were to have some kind of behavior, perhaps a
Point.move_to(somewhere) would be more useful?
So, it depends. :-)
Bo Persson
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2019-08-21 12:52 -0700 |
| Message-ID | <c053c20c-9b56-49c4-ab0a-0d060faa3c89@googlegroups.com> |
| In reply to | #67849 |
On Wednesday, 21 August 2019 22:23:08 UTC+3, JiiPee wrote:
> Which one is better:
>
> 1)
>
> class Person
>
> {
>
> public:
>
> int getAge() { return age;}
>
> void setAge(int a) { age = a;}
>
> private:
>
> int age;
>
> };
>
> or
>
> 2)
>
> struct Person
>
> {
>
> int age;
>
> };
Age is rapidly changing property of a person so it is usually made as
getter function that calculates it based on date of birth of person
and current date. Date of birth is usually const set in constructor
since that can't change during life-time (or even after) of a person.
Snipping possible misrepresentation of Herb Sutter and
CppCoreGuidelines of isocpp.
> I do currently 1) but wondering which way to go.
I think you should do in usual way (that I desribed).
[toc] | [prev] | [next] | [standalone]
| From | JiiPee <no@notvalid.com> |
|---|---|
| Date | 2019-08-22 15:25 +0100 |
| Message-ID | <dBx7F.346070$c8w1.123079@fx08.am4> |
| In reply to | #67856 |
On 21/08/2019 20:52, Öö Tiib wrote: > Snipping possible misrepresentation of Herb Sutter and > CppCoreGuidelines of isocpp. Sutter says like: "Always make all data members private. The only exception is c-style struct where all members are public" So he was against putting some private and some public. And he proves his point. So according to him if Person class has some functions (like increasing the age automatically) then the age itself should be private and if its value is needed we need a getter.
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2019-08-22 09:06 -0700 |
| Message-ID | <1a05f743-f9a4-47e5-8dc6-64abab4195b0@googlegroups.com> |
| In reply to | #67877 |
On Thursday, 22 August 2019 17:25:24 UTC+3, JiiPee wrote: > On 21/08/2019 20:52, Öö Tiib wrote: > > Snipping possible misrepresentation of Herb Sutter and > > CppCoreGuidelines of isocpp. > > > Sutter says like: "Always make all data members private. The only > exception is c-style struct where all members are public" CppCoreGuidelines at <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get> does not conflict with it just suggest to prefer that c-style struct to all trivial setters and getters. That is why your claim seemed misrepresentation. > So he was against putting some private and some public. And he proves > his point. Your OP did not discuss putting some data members private and some public, both are against it: <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c134-ensure-all-non-const-data-members-have-the-same-access-level> > So according to him if Person class has some functions (like increasing > the age automatically) then the age itself should be private and if its > value is needed we need a getter. What you seemingly asked in your OP was if to have trivial setters and getters or to have c-style struct. "Getter" is red herring since you don't need one with c-style struct.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2019-08-24 04:32 -0700 |
| Message-ID | <86h86623z3.fsf@mailhub.linuxsc.com> |
| In reply to | #67879 |
Tiib <ootiib@hot.ee> writes: > On Thursday, 22 August 2019 17:25:24 UTC+3, JiiPee wrote: > >> On 21/08/2019 20:52, Tiib wrote: >> >>> Snipping possible misrepresentation of Herb Sutter and Strange comment considering that nowhere in the thread is any reference given for Herb Sutter's views. Given that you don't know what Herb Sutter writings JiiPee means to refer to here, there is no basis for claiming a misrepresentation, or even a possible misrepresentation (except in the vacuous sense that "all things are possible"). >>> CppCoreGuidelines of isocpp. > >> Sutter says like: "Always make all data members private. The only >> exception is c-style struct where all members are public" > > CppCoreGuidelines at > <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get> > does not conflict with it just suggest to prefer that c-style struct > to all trivial setters and getters. That is why your claim seemed > misrepresentation. For what it's worth, I think JiiPee's comments offer a more faithful representation of the core guidelines document than yours do.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2019-08-22 15:09 -0700 |
| Message-ID | <86y2zk26ps.fsf@mailhub.linuxsc.com> |
| In reply to | #67849 |
JiiPee <no@notvalid.com> writes:
[some white space reformatting done]
> Which one is better: 1)
>
> class Person {
> public:
> int getAge() { return age;}
> void setAge(int a) { age = a;}
> private:
> int age;
> };
>
> or 2)
>
> struct Person {
> int age;
> };
>
> ####
>
> I know Herb Sutter recommended 1) but for example isocpp
>
> https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get
>
> seems to recommend 2). [...]
>
> I do currently 1) but wondering which way to go.
>
> Like now I have a "Settings" class. Simple data members. I started
> adding getters and setters....
I agree with Herb Sutter's recommendation that (assuming the
class or struct has some member functions) data members should
never be public. There are cases where for data members might
plausibly be made protected rather than private, but never
public. (Incidentally I am ignoring the "age/birthday" matter
that some other people have commented on, and assuming your
question is meant as generic, with 'age' being merely an
unfortunate choice of example.)
I suggest however a slightly different pattern than (1), along
these lines (disclaimer: not compiled):
class Person {
unsigned siblings_;
// ... other data members ...
public:
// ... other member functions
unsigned &siblings() { return siblings_; }
const unsigned &siblings() const { return siblings_; }
};
Now our accessor functions look more like data member access, but
they remain functions:
if( fred.siblings() > 0 ) ...
fred.siblings() += 1; // a new birth in fred's family
To me this pattern reads nicer on the client side than set/get
functions.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2019-08-23 16:17 +1200 |
| Message-ID | <gs97lsF3s0U2@mid.individual.net> |
| In reply to | #67890 |
On 23/08/2019 10:09, Tim Rentsch wrote:
> JiiPee <no@notvalid.com> writes:
>
> [some white space reformatting done]
>
>> Which one is better: 1)
>>
>> class Person {
>> public:
>> int getAge() { return age;}
>> void setAge(int a) { age = a;}
>> private:
>> int age;
>> };
>>
>> or 2)
>>
>> struct Person {
>> int age;
>> };
>>
>> ####
>>
>> I know Herb Sutter recommended 1) but for example isocpp
>>
>> https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get
>>
>> seems to recommend 2). [...]
>>
>> I do currently 1) but wondering which way to go.
>>
>> Like now I have a "Settings" class. Simple data members. I started
>> adding getters and setters....
>
> I agree with Herb Sutter's recommendation that (assuming the
> class or struct has some member functions) data members should
> never be public. There are cases where for data members might
> plausibly be made protected rather than private, but never
> public.
There is a case where a data member is safe to be public: a const data
member. Access to such a member cannot change a class's invariants.
--
Ian.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2019-08-23 05:26 -0700 |
| Message-ID | <86tva8131e.fsf@mailhub.linuxsc.com> |
| In reply to | #67897 |
Ian Collins <ian-news@hotmail.com> writes:
> On 23/08/2019 10:09, Tim Rentsch wrote:
>
>> JiiPee <no@notvalid.com> writes:
>>
>> [some white space reformatting done]
>>
>>> Which one is better: 1)
>>>
>>> class Person {
>>> public:
>>> int getAge() { return age;}
>>> void setAge(int a) { age = a;}
>>> private:
>>> int age;
>>> };
>>>
>>> or 2)
>>>
>>> struct Person {
>>> int age;
>>> };
>>>
>>> ####
>>>
>>> I know Herb Sutter recommended 1) but for example isocpp
>>>
>>> https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get
>>>
>>> seems to recommend 2). [...]
>>>
>>> I do currently 1) but wondering which way to go.
>>>
>>> Like now I have a "Settings" class. Simple data members. I started
>>> adding getters and setters....
>>
>> I agree with Herb Sutter's recommendation that (assuming the
>> class or struct has some member functions) data members should
>> never be public. There are cases where for data members might
>> plausibly be made protected rather than private, but never
>> public.
>
> There is a case where a data member is safe to be public: a const
> data member. Access to such a member cannot change a class's
> invariants.
My experience with const data members is that they are almost
always more trouble than they're worth. Even in those cases
where a data member is made const, it's better to stick to the
simple rule that data members (other than pure structs) never be
public, on general principles of information hiding: client code
shouldn't know or care what particular data members a class has,
let alone whether they are const or not. Any property an object
wants to supply to its clients should be made available through a
(usually const) member function, and only that, regardless of
whether the property needs an elaborate computation or is simply
returning the value of a data member -- even a const one.
[toc] | [prev] | [next] | [standalone]
| From | Melzzzzz <Melzzzzz@zzzzz.com> |
|---|---|
| Date | 2019-08-23 18:07 +0000 |
| Message-ID | <LXV7F.35440$hJ3.16176@fx07.am4> |
| In reply to | #67897 |
On 2019-08-23, Ian Collins <ian-news@hotmail.com> wrote:
> On 23/08/2019 10:09, Tim Rentsch wrote:
>> JiiPee <no@notvalid.com> writes:
>>
>> [some white space reformatting done]
>>
>>> Which one is better: 1)
>>>
>>> class Person {
>>> public:
>>> int getAge() { return age;}
>>> void setAge(int a) { age = a;}
>>> private:
>>> int age;
>>> };
>>>
>>> or 2)
>>>
>>> struct Person {
>>> int age;
>>> };
>>>
>>> ####
>>>
>>> I know Herb Sutter recommended 1) but for example isocpp
>>>
>>> https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get
>>>
>>> seems to recommend 2). [...]
>>>
>>> I do currently 1) but wondering which way to go.
>>>
>>> Like now I have a "Settings" class. Simple data members. I started
>>> adding getters and setters....
>>
>> I agree with Herb Sutter's recommendation that (assuming the
>> class or struct has some member functions) data members should
>> never be public. There are cases where for data members might
>> plausibly be made protected rather than private, but never
>> public.
>
> There is a case where a data member is safe to be public: a const data
> member. Access to such a member cannot change a class's invariants.
>
Also there is case when member is class with own interface.
--
press any key to continue or any other to quit...
U ničemu ja ne uživam kao u svom statusu INVALIDA -- Zli Zec
Na divljem zapadu i nije bilo tako puno nasilja, upravo zato jer su svi
bili naoruzani. -- Mladen Gogala
[toc] | [prev] | [next] | [standalone]
| From | JiiPee <no@notvalid.com> |
|---|---|
| Date | 2019-08-23 07:09 +0100 |
| Message-ID | <SqL7F.98411$WI2.78457@fx34.am4> |
| In reply to | #67890 |
On 22/08/2019 23:09, Tim Rentsch wrote:
> (Incidentally I am ignoring the "age/birthday" matter
> that some other people have commented on, and assuming your
> question is meant as generic, with 'age' being merely an
> unfortunate choice of example.)
correct. the example given might not have been the best. general
question about all situations.
>
> I suggest however a slightly different pattern than (1), along
> these lines (disclaimer: not compiled):
>
> class Person {
> unsigned siblings_;
> // ... other data members ...
>
> public:
> // ... other member functions
>
> unsigned &siblings() { return siblings_; }
> const unsigned &siblings() const { return siblings_; }
> };
>
> Now our accessor functions look more like data member access, but
> they remain functions:
>
> if( fred.siblings() > 0 ) ...
>
> fred.siblings() += 1; // a new birth in fred's family
>
> To me this pattern reads nicer on the client side than set/get
> functions.
yes many seems to suggest this online
[toc] | [prev] | [next] | [standalone]
| From | JiiPee <no@notvalid.com> |
|---|---|
| Date | 2019-08-23 07:13 +0100 |
| Message-ID | <0uL7F.49321$Xs5.2002@fx06.am4> |
| In reply to | #67849 |
On 22/08/2019 23:22, Stefan Ram wrote:
> Instead of asking the object for data and the processing
> to data outside of the object (as when using accessors),
> you should tell the object to do the processing itself.
sometimes its about storing global settings like:
struct Settings
{
Color backgroundColor;
int fontSize;
....
};
So I guess this class is not really meant to operate with the values
only return them? it just bundless a group of data.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-08-23 09:30 +0200 |
| Message-ID | <qjo4mm$g40$1@dont-email.me> |
| In reply to | #67900 |
On 23/08/2019 08:13, JiiPee wrote:
> On 22/08/2019 23:22, Stefan Ram wrote:
>> Instead of asking the object for data and the processing
>> to data outside of the object (as when using accessors),
>> you should tell the object to do the processing itself.
>
>
> sometimes its about storing global settings like:
>
> struct Settings
>
> {
>
> Color backgroundColor;
>
> int fontSize;
>
> ....
>
> };
>
>
> So I guess this class is not really meant to operate with the values
> only return them? it just bundless a group of data.
>
Classes like that still need to have protection. There may not be need
for synchronisation between members for keeping invariants, but usually
you don't want to allow any possibility of other parts of the code
making uncoordinated changes to the values.
[toc] | [prev] | [next] | [standalone]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2019-08-25 06:16 +0000 |
| Message-ID | <slrnqm49ua.cdo.grahn+nntp@frailea.sa.invalid> |
| In reply to | #67901 |
On Fri, 2019-08-23, David Brown wrote:
> On 23/08/2019 08:13, JiiPee wrote:
>> On 22/08/2019 23:22, Stefan Ram wrote:
>>> Instead of asking the object for data and the processing
>>> to data outside of the object (as when using accessors),
>>> you should tell the object to do the processing itself.
>>
>>
>> sometimes its about storing global settings like:
>>
>> struct Settings
>> {
>> Color backgroundColor;
>> int fontSize;
>> ....
>> };
>>
>> So I guess this class is not really meant to operate with the values
>> only return them? it just bundless a group of data.
>>
>
> Classes like that still need to have protection. There may not be need
> for synchronisation between members for keeping invariants, but usually
> you don't want to allow any possibility of other parts of the code
> making uncoordinated changes to the values.
Personally, for a config struct I'd ask myself "will I create this
object early and pass it once to the main application logic?". If the
answer is 'yes', I'd happily pass it as const and leave it as it is.
/Jorgen
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-08-25 12:12 +0200 |
| Message-ID | <qjtmva$r9t$2@dont-email.me> |
| In reply to | #67930 |
On 25/08/2019 08:16, Jorgen Grahn wrote:
> On Fri, 2019-08-23, David Brown wrote:
>> On 23/08/2019 08:13, JiiPee wrote:
>>> On 22/08/2019 23:22, Stefan Ram wrote:
>>>> Instead of asking the object for data and the processing
>>>> to data outside of the object (as when using accessors),
>>>> you should tell the object to do the processing itself.
>>>
>>>
>>> sometimes its about storing global settings like:
>>>
>>> struct Settings
>>> {
>>> Color backgroundColor;
>>> int fontSize;
>>> ....
>>> };
>>>
>>> So I guess this class is not really meant to operate with the values
>>> only return them? it just bundless a group of data.
>>>
>>
>> Classes like that still need to have protection. There may not be need
>> for synchronisation between members for keeping invariants, but usually
>> you don't want to allow any possibility of other parts of the code
>> making uncoordinated changes to the values.
>
> Personally, for a config struct I'd ask myself "will I create this
> object early and pass it once to the main application logic?". If the
> answer is 'yes', I'd happily pass it as const and leave it as it is.
>
That could well be sufficient protection, yes.
[toc] | [prev] | [next] | [standalone]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2019-08-23 11:24 +0000 |
| Message-ID | <slrnqlvj7n.cdo.grahn+nntp@frailea.sa.invalid> |
| In reply to | #67849 |
On Thu, 2019-08-22, Stefan Ram wrote: > Supersedes: <accessor-20190822232107@ram.dialup.fu-berlin.de> > [Typos and clarifications] > > JiiPee <no@notvalid.com> writes: >>int age; > A class needs to protect its invariants. > > Therefore, a member can be public only if it is not > mentioned in an invariant of the class. I think invariants (explicit or implicit) is why setters and getters bother me. Either you have a C struct with no invariants, and setters/getters are just unnecessary OO noise on top of non-OO code. Or you /do/ have invariants, and setting an individual member, at any time, threatens to break the invariant. Which doesn't mean there can be /no/ set/get methods, they won't map 1:1 to the members. > An accessor, however, is just appropriate for data > classes where objects effectively are used to represent > records as in non-OOP programming. In OOP they violate > "Tell, Don't Ask!". > > Instead of asking the object for data and then processing > the data outside of the object (as when using accessors), > you should just /tell the object/ to do the processing. Moving logic into the class instead of treating it like a dumb container. Also good advice (except of course when you /want/ a dumb container). /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o .
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2019-08-23 08:34 -0400 |
| Message-ID | <qjomgf$dtc$1@dont-email.me> |
| In reply to | #67902 |
On 8/23/19 7:24 AM, Jorgen Grahn wrote: ... > I think invariants (explicit or implicit) is why setters and getters > bother me. > > Either you have a C struct with no invariants, and setters/getters are > just unnecessary OO noise on top of non-OO code. > > Or you /do/ have invariants, and setting an individual member, at any > time, threatens to break the invariant. Which doesn't mean there can > be /no/ set/get methods, they won't map 1:1 to the members. In general, I agree. However, a setter for a single member could make sense, if the applicable constraints allow two or more different values for that member, even if all other members are unchanged. For instance, the invariant might be current_value <= maximum_achieved_value. The setter for current_value would deal with changes that would violate that invariant, either by rejecting them or by increasing maximum_achieved_value (which corresponds to the last case you mention: a setter that changes two or more members in synchrony).
[toc] | [prev] | [next] | [standalone]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2019-08-23 14:48 +0000 |
| Message-ID | <slrnqlvv5t.cdo.grahn+nntp@frailea.sa.invalid> |
| In reply to | #67905 |
On Fri, 2019-08-23, Stefan Ram wrote: > James Kuyper <jameskuyper@alumni.caltech.edu> writes: >>On 8/23/19 7:24 AM, Jorgen Grahn wrote: >>>Or you /do/ have invariants, and setting an individual member, at any >>>time, threatens to break the invariant. Which doesn't mean there can >>>be /no/ set/get methods, they won't map 1:1 to the members. > .. >>invariant, either by rejecting them or by increasing >>maximum_achieved_value (which corresponds to the last case you mention: >>a setter that changes two or more members in synchrony). When I wrote "map 1:1 to the members" I was more thinking of someone going through all the members and adding a setter for each of them. > Behind all of this lurks the question: How does one define "setter"? How about "a method that's defined in terms of changing a certain part of the object, without considering the object as one single entity"? But I suppose that's my definition of a setter I dislike, rather than of all setters. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o .
[toc] | [prev] | [next] | [standalone]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2019-08-23 15:49 +0000 |
| Message-ID | <slrnqm02np.cdo.grahn+nntp@frailea.sa.invalid> |
| In reply to | #67905 |
On Fri, 2019-08-23, James Kuyper wrote: > On 8/23/19 7:24 AM, Jorgen Grahn wrote: > ... >> I think invariants (explicit or implicit) is why setters and getters >> bother me. >> >> Either you have a C struct with no invariants, and setters/getters are >> just unnecessary OO noise on top of non-OO code. >> >> Or you /do/ have invariants, and setting an individual member, at any >> time, threatens to break the invariant. Which doesn't mean there can >> be /no/ set/get methods, they won't map 1:1 to the members. > > In general, I agree. However, a setter for a single member could make > sense, if the applicable constraints allow two or more different values > for that member, even if all other members are unchanged. For instance, > the invariant might be current_value <= maximum_achieved_value. The > setter for current_value would deal with changes that would violate that > invariant, either by rejecting them or by increasing > maximum_achieved_value (which corresponds to the last case you mention: > a setter that changes two or more members in synchrony). I can imagine how that could end up with me breaking out: ValueWithHighwatermark<int> foo = 2; // 2, 2 foo = 3; // 3, 3 foo = 0; // 0, 3 I know it was just an example, but my gut feeling is that there are often solutions like that: to raise the abstraction level of the members. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o .
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c++
csiph-web