[ACCEPTED]-Reasons to use private instead of protected for fields and methods-protected
There is some consensus that one should 25 prefer composition over inheritance in OOP. There are several reasons for this 24 (google if you're interested), but the main 23 part is that:
- inheritance is seldom the best tool and is not as flexible as other solutions
- the protected members/fields form an interface towards your subclasses
- interfaces (and assumptions about their future use) are tricky to get right and document properly
Therefore, if you choose to 22 make your class inheritable, you should 21 do so conciously and with all the pros and 20 cons in mind.
Hence, it's better not to 19 make the class inheritable and instead make 18 sure it's as flexible as possible (and no 17 more) by using other means.
This is mostly 16 obvious in larger frameworks where your 15 class's usage is beyond your control. For 14 your own little app, you won't notice this 13 as much, but it (inheritance-by-default) will bite 12 you in the behind sooner or later if you're 11 not careful.
Alternatives
Composition means that you'd 10 expose customizability through explicit 9 (fully abstract) interfaces (virtual or 8 template-based).
So, instead of having an 7 Vehicle base class with a virtual drive() function 6 (along with everything else, such as an 5 integer for price, etc.), you'd have a Vehicle 4 class taking a Motor interface object, and 3 that Motor interface only exposes the drive() function. Now 2 you can add and re-use any sort of motor 1 anywhere (more or less. :).
There are two situations where it matters 94 whether a member is protected
or private
:
- If a derived class could benefit from using a member, making the member `protected` would allow it to do so, while making it `private` would deny it that benefit.
- If a future version of the base class could benefit by not having the member behave as it does in the present version, making the member `private` would allow that future version to change the behavior (or eliminate the member entirely), while making it `protected` would require all future versions of the class to keep the same behavior, thus denying them the benefit that could be reaped from changing it.
If one can imagine 93 a realistic scenario where a derived class 92 might benefit from being able to access 91 the member, and cannot imagine a scenario 90 where the base class might benefit from 89 changing its behavior, then the member should 88 be protected
[assuming, of course, that it shouldn't 87 be public]. If one cannot imagine a scenario 86 where a derived class would get much benefit 85 from accessing the member directly, but 84 one can imagine scenarios where a future 83 version of the base class might benefit 82 by changing it, then it should be private
. Those 81 cases are pretty clear and straightforward.
If 80 there isn't any plausible scenario where 79 the base class would benefit from changing 78 the member, I would suggest that one should 77 lean toward making it protected
. Some would say 76 the "YAGNI" (You Ain't Gonna Need It) principle 75 favors private
, but I disagree. If you're is expecting 74 others to inherit the class, making a member 73 private doesn't assume "YAGNI", but rather 72 "HAGNI" (He's Not Gonna Need It). Unless 71 "you" are going to need to change the behavior 70 of the item in a future version of the class, "you" ain't 69 gonna need it to be private
. By contrast, in many 68 cases you'll have no way of predicting what 67 consumers of your class might need. That 66 doesn't mean one should make members protected
without 65 first trying to identify ways one might 64 benefit from changing them, since YAGNI
isn't 63 really applicable to either decision. YAGNI 62 applies in cases where it will be possible 61 to deal with a future need if and when it 60 is encountered, so there's no need to deal 59 with it now. A decision to make a member 58 of a class which is given to other programmers 57 private
or protected
implies a decision as to which type 56 of potential future need will be provided 55 for, and will make it difficult to provide 54 for the other.
Sometimes both scenarios will 53 be plausible, in which case it may be helpful 52 to offer two classes--one of which exposes 51 the members in question and a class derived 50 from that which does not (there's no standard 49 idiomatic was for a derived class to hide 48 members inherited from its parent, though 47 declaring new members which have the same 46 names but no compilable functionality and 45 are marked with an Obsolete
attribute would have 44 that effect). As an example of the trade-offs 43 involved, consider List<T>
. If the type exposed 42 the backing array as a protected member, it 41 would be possible to define a derived type 40 CompareExchangeableList<T> where T:Class
which included a member T CompareExchangeItem(index, T T newValue, T oldvalue)
which would return 39 Interlocked.CompareExchange(_backingArray[index], newValue, oldValue)
; such a type could be used by any code 38 which expected a List<T>
, but code which knew the 37 instance was a CompareExchangeableList<T>
could use the CompareExchangeItem
on it. Unfortunately, because 36 List<T>
does not expose the backing array to derived 35 classes, it is impossible to define a type 34 which allows CompareExchange
on list items but which would 33 still be useable by code expecting a List<T>
.
Still, that's 32 not to imply that exposing the backing array 31 would have been completely without cost; even 30 though all extant implementations of List<T>
use 29 a single backing array, Microsoft might 28 implement future versions to use multiple 27 arrays when a list would otherwise grow 26 beyond 84K, so as to avoid the inefficiencies 25 associated with the Large Object Heap. If 24 the backing array was exposed as protected 23 member, it would be impossible to implement 22 such a change without breaking any code 21 that relied upon that member.
Actually, the 20 ideal thing might have been to balance those 19 interests by providing a protected member 18 which, given a list-item index, will return 17 an array segment which contains the indicated 16 item. If there's only one array, the method 15 would always return a reference to that 14 array, with an offset of zero, a starting 13 subscript of zero, and a length equal to 12 the list length. If a future version of 11 List<T>
split the array into multiple pieces, the 10 method could allow derived classes to efficiently 9 access segments of the array in ways that 8 would not be possible without such access 7 [e.g. using Array.Copy
] but List<T>
could change the way 6 it manages its backing store without breaking 5 properly-written derived classes. Improperly-written 4 derived classes could get broken if the 3 base implementation changes, but that's 2 the fault of the derived class, not the 1 base.
I just prefer private than protected in 4 the default case because I'm following the 3 principle to hide as much as possibility 2 and that's why set the visibility as low 1 as possible.
I am reaching here. However, I think that 39 the use of Protected member variables should 38 be made conciously, because you not only 37 plan to inherit, but also because there 36 is a solid reason derived classed shouldn't 35 use the Property Setters/Getters defined 34 on the base class.
In OOP, we "encapsulate" the 33 member fields so that we can excercise control 32 over how they properties the represent are 31 accessed and changed. When we define a getter/setter 30 on our base for a member variable, we are 29 essentially saying that THIS is how I want 28 this variable to be referenced/used.
While 27 there are design-driven exceptions in which 26 one might need to alter the behavior created 25 in the base class getter/setter methods, it 24 seems to me that this would be a decision 23 made after careful consideration of alternatives.
For 22 Example, when I find myself needing to access 21 a member field from a derived class directly, instead 20 of through the getter/setter, I start thinking 19 maybe that particular Property should be 18 defined as abstract, or even moved to the 17 derived class. This depends upon how broad 16 the hierarchy is, and any number of additional 15 considerations. But to me, stepping around 14 the public Property defined on the base 13 class begins to smell.
Of course, in many 12 cases, it "doesn't matter" because we are 11 not implementing anything within the getter/setter 10 beyond access to the variable. But again, if 9 this is the case, the derived class can 8 just as easily access through the getter/setter. This 7 also protects against hard-to-find bugs 6 later, if employed consistently. If the 5 behgavior of the getter/setter for a member 4 field on the base class is changed in some 3 way, and a derived class references the 2 Protected field directly, there is the potential 1 for trouble.
You are on the right track. You make something 15 private, because your implementation is 14 dependant on it not being changed either 13 by a user or descendant.
I default to private 12 and then make a conscious decision about 11 whether and how much of the inner workings 10 I'm going to expose, you seem to work on 9 the basis, that it will be exposed anyway, so 8 get on with it. As long as we both remember 7 to cross all the eyes and dot all the tees, we 6 are good.
Another way to look at it is this. If 5 you make it private, some one might not 4 be able to do what they want with your implementation.
If 3 you don't make it private, someone may be 2 able to do something you really don't want 1 them to do with your implementation.
I've been programming OOP since C++ in 1993 31 and Java in 1995. Time and again I've seen 30 a need to augment or revise a class, typically 29 adding extra functionality tightly integrated 28 with the class. The OOP way to do so is 27 to subclass the base class and make the 26 changes in the subclass. For example a base 25 class field originally referred to only 24 elsewhere in the base class is needed for 23 some other action, or some other activity 22 must change a value of the field (or one 21 of the field's contained members). If that 20 field is private in the base class then 19 the subclass cannot access it, cannot extend 18 the functionality. If the field is protected 17 it can do so.
Subclasses have a special relationship 16 to the base class that other classes elsewhere 15 in the class hierarchy don't have: they 14 inherit the base class members. The purpose 13 of inheritance is to access base class members; private 12 thwarts inheritance. How is the base class 11 developer supposed to know that no subclasses 10 will ever need to access a member? In some 9 cases that can be clear, but private should 8 be the exception rather than the rule. Developers 7 subclassing the base class have the base 6 class source code, so their alternative 5 is to revise the base class directly (perhaps 4 just changing private status to protected 3 before subclassing). That's not clean, good 2 practice, but that's what private makes 1 you do.
I am a beginner at OOP but have been around 27 since the first articles in ACM and IEEE. From 26 what I remember, this style of development 25 was more for modelling something. In the 24 real world, things including processes and 23 operations would have "private, protected, and 22 public" elements. So to be true to the object 21 .....
Out side of modelling something, programming 20 is more about solving a problem. The issue 19 of "private, protected, and public" elements 18 is only a concern when it relates to making 17 a reliable solution. As a problem solver, I 16 would not make the mistake of getting cough 15 up in how others are using MY solution to 14 solve their own problems. Now keep in mind 13 that a main reason for the issue of ...., was 12 to allow a place for data checking (i.e., verifying 11 the data is in a valid range and structure 10 before using it in your object).
With that 9 in mind, if your code solves the problem 8 it was designed for, you have done your 7 job. If others need your solution to solve 6 the same or a simular problem - Well, do 5 you really need to control how they do it. I 4 would say, "only if you are getting some 3 benefit for it or you know the weaknesses 2 in your design, so you need to protect some 1 things."
In my idea, if you are using DI (Dependency 8 Injection) in your project and you are using 7 it to inject some interfaces in your class 6 (by constructor) to use them in your code, then 5 they should be protected, cause usually 4 these types of classes are more like services 3 not data keepers.
But if you want to use 2 attributes to save some data in your class, then 1 privates would be better.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.