I'm extending a libary class which has a public Method that I don't wan't to be callable from the outside. I know that I can hide it using the "new" keyword, but the problem is, that it has a lot of different declarations.
Something like this:
class Parent() {
public double method(double a, double b) { ... }
public int method(int a, int b) { ... }
public System.Int32 method(System.Int32 a, System.Int32 b) { ... }
}
Now I could do:
class Child() {
// Make method private.
private new double method(double a, double b) { return base.method(a, b) }
private new int method(int a, int b) { return base.method(a, b) }
private new System.Int32 method(System.Int32 a, System.Int32 b) { return base.method(a, b) }
/// Own Code.
}
But I'm wondering if there is not a simpler way to make all overrides of that function private.
I think the first question is whether or not your descendant class needs to be cast as the parent.
If not, then the best way would be to use a facade pattern in which you hide the "parent" and only allow access to it through your methods.
Kind of like:
class Parent {
public double method(double a, double b) { ... }
public int method(int a, int b) { ... }
}
class YourStuff {
private Parent _parent = new Parent();
public int AddNumbers(int a, int b) {
return _parent.method(a,b);
}
}
In this case, the Parent class is hidden.
That's not the way method hiding works. Your private new methods only hide the original methods inside the Child class (but they call what they hide, so nothing's gained).
In a Grandchild class deriving from Child, nothing is hidden anymore because the private new methods are not in scope, so the public methods of Parent are perfectly callable and "naked". Method hiding does not remove the hidden method in any way; it's just a matter of which of the identical methods gets called.
If you want that your library class Parent method which name Method will not be callable from the outside you need to change access modifier. Your class hasn't access modifier, so, be default it is Internal - The type or member can be accessed by any code in the same assembly, but not from another assembly. The same accessibility is for method Method as it has access modifier public. If you want that implemented in class Method can be accessible only for derived class instance you need all access modifiers public for overloaded Method variations to change to protected and then in a child class hide this method overloaded methods. If you want these hidden methods to be used from outside you need to change their access modifiers from private to public. Example of this implementation:
namespace HideBaseClassMethod
{
class Program
{
static void Main(string[] args)
{
Parent myParent = new Parent();
//myParent. - no one of overloaded protected methods are accessible after dot operator
Child myChild = new Child();
myChild.Method(2.5, 4.3); //double
myChild.Method(2, 4);//int
Parent myChildCreatedAsParent = new Child();
//myChildCreatedAsParent. - no one of overloaded protected methods are accessible after dot operator
}
}
class Parent
{
protected double Method(double a, double b)
{
Console.WriteLine($"I am a parent double method {a} + {b}");
return a + b;
}
protected int Method(int a, int b)
{
Console.WriteLine($"I am a parent integer method {a} + {b}");
return a + b;
}
}
class Child:Parent
{
public new double Method(double a, double b)
{
Console.WriteLine($"I am a child double method {a} * {b}");
return a * b;
}
public new int Method(int a, int b)
{
Console.WriteLine($"I am a child integer method {a} * {b}");
return a + b;
}
}
}
The result of this program execution will be:
I am a child double method 2.5 * 4.3
I am a child integer method 2 * 4
Related
public class a
{
protected virtual int mult(int x)
{
return x * x;
}
}
public class b : a
{
protected override int mult(int x) { return x * x * x; }
}
internal class Program
{
static void Main(string[] args)
{
b jack = new b();
int v = jack.mult(5); // error
// so how can I access mult() in the main class without changing the access modifier to public ??????
}
}
How to access a function whose access modifier is protected and exists in a class that inherits from another class in c#?
Note that the mult function is declared as protected in both class a and class b, which means that it can only be accessed by code within the class or its derived classes. Since b is a derived class of a, the mult function is accessible to code within b.
If you want to access the mult function from a class other than b or a subclass of b, you will need to change the access modifier to the public or provide a public method in b or a subclass of b that calls the mult function.
In this case you are doing all this in the Main method which is in other class than a or b.
Is it possible to access the method that has been overridden using the object of the derived class?
using System;
class Bclass
{
public virtual int result(int a,int b)
{
return a + b;
}
}
class Dclass:Bclass
{
public override int result(int a, int b)
{
return a - b;
}
}
public class Program
{
static public void Main(string[] args)
{
Dclass obj1 = new Dclass();
Console.WriteLine(obj1.result(10, 5));
}
}
Is there a way to get the output as 15?
From MSDN documentation:
The override modifier is required to extend or modify the abstract or
virtual implementation of an inherited method, property, indexer, or
event.
override modifier are designed to extend functionality of virtual function. When ever you call overridden function with the help of derived class object it will call overridden function.
To answer your question,
Is it possible to access the method that has been overridden using the
object of the derived class?
There is no way to call virtual method directly using derived class object
Ways to call virtual method:
Approach 1:
Create a new function in derived class and call base.result() from it.
public int BaseResult(int a, int b)
{
return base.result(a, b);
}
and call BaseResult() using derived class instance
Dclass obj1 = new Dclass();
Console.WriteLine(obj1.BaseResult(10, 5));
Try it online
Approach 2:
Create instance of base class and from that access virtual method.
Bclass obj2 = new Bclass();
Console.WriteLine(obj2.result(10, 5));
Unless you need to declare the base method as virtual for some reason, you could also achieve what you want by declaring the derived class method as new, thereby hiding the implementation when using it through an instance of the derived class.
At the same time, you can still access the base implementation by casting the object to the base class.
Following the example you provided:
class Bclass
{
public int result(int a,int b)
{
return a + b;
}
}
class Dclass : Bclass
{
public new int result(int a, int b)
{
return a - b;
}
public int BaseResult(int a, int b)
{
return base.result(a, b);
}
}
public class Program
{
public static void Main(string[] args)
{
Dclass obj1 = new Dclass();
Console.WriteLine(((Bclass)obj1).result(10, 5)); // 15
}
}
More information about the differences between override and new can be found in this MSDN article.
experts,
below is code for abstract class with virtual method and override in class B.
Can we call method M1 of class A, as we can't instantiate this? thanks,
public abstract class A
{
public virtual int M1(int a, int b)
{
return a + b;
}
}
public class B : A
{
public override int M1(int a, int b)
{
return a - b;
}
}
As soon as B overrides M1 virtual method dispatch will make B.M1() being called, even when you cast instance of B to A.
The only place you can call it is from within B code, using base.M1() syntax:
public override int M1(int a, int b)
{
var temp = base.M1(a, b);
return temp - a - b;
}
However, there can be another class inheriting from A (lets name it C), which does not override M1. In that case, calling M1 on instance of C will invoke A.M1().
You must instantiate a class that implements A1, virtual is a method you CAN override but if you don't it will execute the base class method.
Since we know that constructor is not inherited in the child class as i asked in the my previous question Click here to view question
I had write the code
namespace TestConscoleApplication
{
abstract public class A
{
public int c;
public int d;
private A(int a, int b)
{
c = a;
d = b;
}
public virtual void Display1()
{
Console.WriteLine("{0}{1}", c, d);
}
}
internal class B : A
{
protected string Msg;
public B(string Err)
{
Msg = Err;
}
public void Display()
{
Console.WriteLine(Msg);
}
}
class Program
{
static void Main(string[] args)
{
B ObjB = new B("Hello");
Console.ReadLine();
}
}
}
when i compile the code its showing an error
Error TestConscoleApplication.A.A(int, int) is inaccessible due to its protection level.
Then why it is showing an error.
By making the only constructor of A private, you've prevented derived classes from being able to be constructed outside A.
Derived class constructor always call the base constructor (one of). Making it private you prohibit access to it from outside. In other words you make it impossible to make an instance of A outside A.
Since you made a constructor, the compiler won't generate a default public one for this class for you.
If you want to provide access to it from the class descendant but not from outside, you should make it protected.
You need to have a constructor for A accessible to B, and use it. Also, the default base constructor is base() (i.e. the parameterless constructor), which doesn't exist on A. Here's one way you can resolve this (nonessential bits removed):
abstract public class A
{
protected A(int a, int b)
{
}
}
internal class B : A
{
public B(int a, int b, string Err)
: base(a, b)
{
}
}
constructors shouldn't be private otherwise you will not be able to create an instance of that class and won't be able to inherit it too, but if you want to create a private constructor create a public one with it too.
For more info Go here
I'm wondering if the following is possible:
class A
{
public int SomeMethod()
{
return 1;
}
}
class B : A
{
public override int SomeMethod()
{
return 3;
}
}
class DrivingClass
{
public static void Main()
{
B classB = new B();
A classA = (A)classB;
Assert.IsEqual(3, classA.SomeMethod());
}
}
This fails of course expecting 3 but actual is 1. Is there a way (without typecasting it back to B) for classA.SomeMethod() to call the overridden version since it started out as B(although I assume this knowledge is lost once casted).
UPDATE:
Class A is already written and for all intents and purposes can not be edited. I can only control class B. Knowing the class B will be casted to type A, I simply want my implementation to be used when SomeMethod() is called on my typecasted B.
SomeMethod needs to be declared as virtual in A in order to successfully override it in B.
public virtual int SomeMethod() // in A
public override int SomeMethod() // in B
With this properly in place
A a = new B();
int value = a.SomeMethod();
Debug.Assert(value == 3); // succeeds
If you instead have
public int SomeMethod() // in A
public new int SomeMethod() // in B, or just
public int SomeMethod() // in B
Then the above assertion fails. The method in B hides the base method, but only via the B reference. When operating under the reference of A, you get the base behaviors.
A a = new B();
int value = a.SomeMethod(); // gets 1 from A, not 3 from B
UPDATE: Class A is already written and for all intents and purposes can not be edited. I can only control class B. Knowing the class B will be casted to type A, I simply want my implementation to be used when SomeMethod() is called on my typecasted B.
Methods are not virtual by default in C#. If the authors of A did not design it with extensibility in mind (at least, as far as overriding SomeMethod), you will not be able to replace or override that behavior with B when it is being treated as A. However, if you are in a position to control the casting, or rather the dependency of the code, you can perhaps invert it so that A actually adheres to the contract of B, not the other way around. Consider the Adapter Pattern, for example.
interface IB
{
int SomeMethod();
}
class B : IB
{
public int SomeMethod() { return 3; }
}
class ABAdapter : IB
{
private A a;
public ABAdapter(A a) { this.a = a; }
public int SomeMethod() { return a.SomeMethod(); }
}
In this example, you've used the adapter to pattern to make A actually fulfill the contract of B, via the IB interface. So code that might once have depended upon A or B can now depend upon IB. The ABAdapter simply delegates to the A implementation.
public void DoSomething(IB ib) // given
A a = new A();
DoSomething(new ABAdapter(a)); // invoke with A
DoSomething(new B()); // invoke with B
You haven't declared SomeMethod to be virtual in A, so this clearly isn't your real code (as otherwise B can't override it) but when you make that change, it will return 3. If it didn't, polymorphism would be completely broken.
Now, the other change we could make to the code you've posted is in B. If you use:
public new int SomeMethod()
{
return 3;
}
Then your assertion would fail - because it would be calling A.SomeMethod() which is shadowed or hidden by B.SomeMethod(), not overridden. Basically, if you want polymorphic behaviour, you need to use override, and it has to be on a virtual method.
I suggest reading up on the topic here
In the article it shows these code examples:
class A
{
public void F() { Console.WriteLine("A.F"); }
public virtual void G() { Console.WriteLine("A.G"); }
}
class B: A
{
new public void F() { Console.WriteLine("B.F"); }
public override void G() { Console.WriteLine("B.G"); }
}
class Test
{
static void Main() {
B b = new B();
A a = b;
a.F(); //prints A.F
b.F(); //prints B.F
a.G(); //prints B.G (due to virtual method override)
b.G(); //prints B.G
}
}
Given your edit stating that you cannot redefine class A, I'm afraid you're more or less out of luck.
It's possible to derive B from A, and then declare new int SomeMethod(), but you won't be able to call that method with an A reference. You could use a run-time type check:
int CallSomeMethod(A obj)
{
var b = obj as B;
return b == null ? obj.SomeMethod() : b.SomeMethod();
}