Why am I Allowed Method Access Less Restrictive Than Class Access

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 add public 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



Leave a reply



Submit