简体   繁体   中英

getters and setters for superclasses?

Is it still standard practice to provide getters and setters in the superclass, for subclasses to access the attributes of the superclass (in other words set the attributes as private)? Or should the attributes be accessed directly (declaring the attributes as protected) by the subclasses?

Is there a standard convention?

It depends entirely on what you want to accomplish.

If you want the superclass attributes to be accessible without being inherited, then you need to declare public getters and setters.

If, on the other hand, you want the members to be accessible only if the superclass is inherited, then you need to declare protected members.

If you want some form of validation, you need getters and setters. This protects the superclass from inadvertent corruption, even if it is inherited.

When I was in university doing my CS degree we were told don't do getters and setters in second year and do them in fifth year.

My personal preference, is to use getters and setters where absolutely required only and to never ever have public variables.

Check the top two answers to this question:

Are getters and setters poor design? Contradictory advice seen

Not a great answer to your question but you are obviously concerned with coding good OO so you should give them some thought.

In Java I prefer to make all my fields private. If I really need to expose something, I create a separate, protected getter for the field. (For example if the interface I'm implementing requires a broader return type than what I want to pass between the different levels of implementations.)

With tools that can generate getters/setters at a click of the mouse, I never felt the need to break encapsulation even between parent/child classes.

Speaking for the C# side, if you have a data member (field or property) that is not public, but is useful to child classes and should be available both to read and write, then declare that member as protected.

If the member should be read by subclasses but not written, you can define the member as a property that is protected but with a private setter:

//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;}
}

This makes MyValue completely hidden from classes outside the inheritance hierarchy, and read-only to subclasses; only the superclass itself can set the value. This would be equivalent to a private field with a protected getter method and a private setter method.

In general, as the designer of the superclass, it's up to you to define how subclasses should be able to use what you provide. If you make something protected, assume subclasses will do anything that "protected" allows them to do. Both C# and Java have methods by which you can independently control the visibility of read and write access.

Seems that in C#, the standard practice is to use properties with get/set accessors. In the simplified form you'll have:

public string Name { get; set; }

But you may have finer control over the access level, for example:

public string Name { get; protected set; }

Here you publicly expose the get method, but leave the set method to derived classes only.

One other benefit of using accessors instead of directly accessing a data member is that you could put a break point on a get/set method and see who executed the method.
This, however, is not possible with the { get; set; } { get; set; } { get; set; } trick. You'll have to write the whole expanded property form:

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

It will be safe to reflect the same concept for Java.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM