Whats the use of less restrictive member access modifiers than the class access modifier?
Is my understanding correct?
Yes.
What could be valid reasons to have less restrictive member access modifiers?
Two reasons:
- Sometimes, you're implementing an interface; interface methods must be
public
- It makes it easier to change the overall access of your class. For instance, if you mark all the methods that you'd ever want to be public
public
, even in a package-private class, then later all you have to do to make the class public is addpublic
to the class declaration.
Finally, what are there best practice to follow?
That's a matter of opinion, so not well-suited to a Stack Overflow question or answer. Do what seems reasonable to you and/or your team, and/or do what your team's style guide tells you to do.
Why C++ allows to give more restrictive access to a derived class method?
It has more to do with it never being disallowed. And now it's too late: too much code would break. Do remember that C++ is a considerably older language than either Java or C#.
But the C++ philosophy inspires you to ask "why disallow it?". It could even be useful: some folk exploit it and make overridden methods private. The amount of documentation you should attach to a private method can be significantly less than a public method. This means you don't repeat yourself and are compelled to rely on the public / protected method in a base class for comments.
Java: Access modifier more restrictive than 'protected', less restrictive than 'private'?
There are only four access levels for fields in Java:
private
- package-private (default; no access modifier)
protected
public
protected
will allow subclasses, other classes in the same package, and members in the class itself to access the protected
member.
The short answer is, there is no way to achieve exactly what is desired.
For a description of those four access modifiers, Controlling Access to Members of a Class from The Java Tutorials has more specific information.
Why derived class overriding method should not be more restrictive than base class in java?
The point is that a caller who only knows about your superclass should still be able to use any instance of the subclass that it's given. Consider this situation:
public class Super
{
public void print()
{
System.out.println("Hello!");
}
}
public class Sub extends Super
{
@Override
void print() // Invalid
{
System.out.println("Package access");
}
}
Now from a different package, imagine we had:
public void printSuper(Super x)
{
x.print();
}
and we called that with:
printSuper(new Sub());
What would you expect that to do? You're overriding the method, so it should print "package access" - but then that means you're calling a package access method from a different package...
Basically, this is just one example of the Liskov Substitution Principle in action. You should be able to treat any instance of a subclass as an instance of the superclass, and it's hard to see how that fits in with making things more restrictive in a subclass.
When overriding a method, why can I increase access but not decrease it?
It's a fundamental principle in OOP: the child class is a fully-fledged instance of the parent class, and must therefore present at least the same interface as the parent class. Making protected/public things less visible would violate this idea; you could make child classes unusable as instances of the parent class.
Why we can't use access modifier in the methods of class which implements two interfaces consist of same methods?
The distinction is not so much about "1 interface vs 2 interfaces", but rather "implicit vs explicit interface implementations". An explanation as for the "why is a visibility modifier forbidden" part of the question, I'll refer to question Why in C# does one need to mention the access modifier for implementation of an interface property?.
(Explicit interface implementations are implicitly public. Yes, you read that correctly.)
C# allows you to implement a single interface both implicitly and explicitly and they become different methods. The static type of the object determines which method to call:
interface IFace {
void Method();
void OnlyImplicit();
void OnlyExplicit();
}
public class Obj : IFace {
public void Method() {
Console.WriteLine("implicit implementation");
}
void IFace.Method() {
Console.WriteLine("explicit implementation");
}
public void OnlyImplicit() {
Console.WriteLine("only implemented implicitly");
}
void IFace.OnlyExplicit() {
Console.WriteLine("only implemented explicitly");
}
public void Main() {
Obj o = new Obj(); // or: var o = new Obj();
IFace i = o;
o.Method(); // call of implicit impl
i.Method(); // call of explicit impl
o.OnlyImplicit(); // call of implicit impl
i.OnlyImplicit(); // call of implicit impl
i.OnlyExplicit(); // call of explicit impl
// compile error, method is implemented explicitly,
// can only be called when static type is interface;
// cannot be called when static type is the class' type
// (this is not so obvious):
o.OnlyExplicit();
}
}
Why can't we change access modifier while overriding methods in C#?
Changing the access modifier of a method in a derived type is pointless that's why it's not allowed:
Case 1: Override with a more restrictive access
This case is obviously not allowed due to the following situation:
class Base
{
public virtual void A() {}
}
class Derived: Base
{
protected override void A()
}
Now we could say:
List<Base> list;
list.Add(new Derived());
list[0].A() //Runtime access exception
Case 2: Overriding with a less restrictive access modifier
What is the point? Hide the method and you are done.
Obviously if someone calls through the base type they will not have access to the new method defined in the derived type but that is consistent with how the author of the base type wanted things to be so you have no "right" to change that. If you want the specifics of the derived class call from the derived class, in which case the new
method works perfectly fine.
EDIT: Expanding case 2
What I am trying to say in case 2, is that you already have the means to change accessibility of any method (virtual or not) if you want to change accessibility.
Consider the following code:
public class Base
{
protected virtual string WhoAmI()
{
return "Base";
}
}
public class Derived : Base
{
public new virtual string WhoAmI()
{
return "Derived";
}
}
public class AnotherDerived : Derived
{
public override string WhoAmI()
{
return "AnotherDerived";
}
}
With the new
keyword you have effectively created a new virtual method for your Derived
class with the same name and signature. Take note that it is ALLOWED to declare a new
method virtual
, so any class deriving from Derived
will be allowed to override it.
What is not allowed is to have someone do the following:
Base newBaseObject = new Derived();
newBaseObject.WhoAmI() //WhoAmI is not accessible.
But this fact has nothing to do with being able to override WhoAmI()
or not. Whatever the case this situation can never be because Base
does not declare a public
WhoAmI()
.
So in a theoretical C# where Derived.WhoAmI()
could override Base.WhoAmI()
there is no practical benefits in doing so because you will never be able to call the virtual method from the base class anyways, so the new
option already meets your requirements.
I hope this makes it clearer.
Related Topics
How Constant Is the Firebase Anonymous Id
When and How to Use @Noreturn Attribute in Swift
In Swift, Can You Split a String by Another String, Not Just a Character
Arkit - Viewport Size VS Real Screen Resolution
Why Does Swift Playground Shows Wrong Number of Executions
Transform a Swift Sequence in to Adjacent Pairs
How to Include Assets/Resources in a Swift Package Manager Library
Method' Is Ambiguous for Type Lookup in This Context, Error in Alamofire
Swift Combine Sink Stops Receiving Values After First Error
In Swiftui, Where Are the Control Events, I.E. Scrollviewdidscroll to Detect the Bottom of List Data
Drag Rotate a Node Around a Fixed Point
Make a Uibarbuttonitem Disappear Using Swift iOS
Swiftui - Wait Until Firestore Getdocuments() Is Finished Before Moving On
Is This a Good Way to Display Asynchronous Data
I Won't Be Able to Return a Value with Alamofire in Swift