Why Can't We Change Access Modifier While Overriding Methods in C#

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.

Cannot change access modifiers when overriding 'public' inherited member '

The title is very clear - an override method must match the virtual method it overrides, not only by it's signature (name and parameters), but also by it's access modifiers and return type.

Why? because of (at least) Polymorphism and method overloading rules.

Polymorphism which is a base principle of object oriented programming is basically the ability to look at a derived class as if it was it's base class. This means that if the base class have a method like public void move(), the derived class also have this method - either inherited unchanged or overrided in the derived class.

The rule for method overloading is very simple - you can have multiple methods with the same name but different signature. The signature of the method is the combination of it's name and it's arguments - so overloads that differs only by return type or access modifiers are not permitted.

Imagine if the compiler would allow you to change the access modifier in inheritance - you would end up with a class like this:

WARNING: Incorrect code ahead!

public class Transport
{
public virtual void Move() { Console.WriteLine("trans Moves"); }
}

public class AutoToTravelAdapter : Transport
{
private Auto auto = new Auto();
private override void Move()
{
auto.Drive();
}
}

So AutoToTravelAdapter would have, in fact, two Move methods with identical signature - one private that is declared in AutoToTravelAdapter class, and one public that is inherited from Transport.

Obviously, this would make calling the Move() method from inside the AutoToTravelAdapter class impossible, since the compiler would have no way to distinguish between the two methods.

Why a function with protected modifier can be overridden and accessible every where?

There's no purpose in preventing the override. The derived class could implement a trivial forwarding function that allows access. Consider:

public class A {
protected virtual void foo() {
writefln("A.foo() called.");
}
};

public class B : A {
protected override void foo() { // OK
writefln("B.foo() called.");
}
public void call_foo() {
foo(); // But I allowed public access anyway!
}
};

Thus, even though I didn't redefine the access level of foo, I still allowed public access to it and there's nothing you can do about it. Allowing the redefinition is just simpler.

Change the access modifier of an overridden method in Java?

Java doesn't let you make the access modifier more restrictive, because that would violate the rule that a subclass instance should be useable in place of a superclass instance. But when it comes to making the access less restrictive... well, perhaps the superclass was written by a different person, and they didn't anticipate the way you want to use their class.

The programs people write and the situations which arise when programming are so varied, that it's better for language designers not to "second-guess" what programmers might want to do with their language. If there is no good reason why a programmer should not be able to make access specifiers less restrictive in a subclass (for example), then it's better to leave that decision to the programmer. They know the specifics of their individual situation, but the language designer does not. So I think this was a good call by the designers of Java.

How to increase the access modifier of a property

You can do this by using "new" instead of "override" to hide the parent's protected property as follows:

public class ChildOne : Parent
{
public new int PropertyOne // No Compiler Error
{
get { return base.PropertyOne; }
set { base.PropertyOne = value; }
}
// PropertyTwo is not available to users of ChildOne
}

public class ChildTwo : Parent
{
// PropertyOne is not available to users of ChildTwo
public new int PropertyTwo
{
get { return base.PropertyTwo; }
set { base.PropertyTwo = value; }
}
}

How to change access modifier without hiding class base variable?

I'm in agreement with @madreflection in thinking a wrapper or decorator is the way to go. That said, setting the properties in question using the base will work.

public class ProcessWithData : Process
{
public ProcessWithData(string filename)
{
base.StartInfo.FileName = filename;
}

public EventHandler CurrentEventHandler { get; private set; }

public void SetHandler(EventHandler eventHandler)
{
// set Exited via base object
if (CurrentEventHandler != null) base.Exited -= CurrentEventHandler;
CurrentEventHandler = eventHandler;
base.Exited += CurrentEventHandler;
}
}

... and use it like so, it's a little more verbose but it works...

var proc = new ProcessWithData("foo.exe");
proc.SetHandler(ProcOnExited);
proc.EnableRaisingEvents = true;
proc.Start();

private void ProcOnExited(object sender, EventArgs e)
{
// do stuff
}

What's the purpose of access modifier in overriden method?

To illustrate Jon's point in code, consider the following:

class LevelOne
{
public virtual void SayHi()
{
Console.WriteLine("Hi!");
}
}
class LevelTwo : LevelOne
{
override void SayHi()
{
Console.WriteLine("Hi!");
}
}
class LevelThree : LevelTwo
{
override void SayHi()
{
Console.WriteLine("Hi!");
}
}

Ad infinitum. Now imagine you're at n-depth of derived classes, you have to follow the inheritance hierarchy all the way back to the original base class to find out the access modifier of the method. That's just plain annoying!

Is there a reason you can not define the access modifier on a method or in an interface?

The interface defines a contract between an object and clients that call its members. A private method cannot be accessed by any other objects so it doesn't make sense to add it to the interface. All members of an interface are considered public for this reason.



Related Topics



Leave a reply



Submit