I have a base class (A) that I have built with some base functionality, and now want to create a subclass (B) with some custom functionality from an external third class (C), which can still be treated as an object of type A.
As I understand it, C# doesn't allow a class to inherit from more than one class, and the typical approach to this kind of problem is to change the base class to an interface, so that the subclass can still inherit from C, and implement A as an interface. However I also want A to provide some default method implementations, which B may override and call. I can't seem to find any way to call A.someMethod() from B if B has it's own implementation of someMethod().
I've put together a code example which hopefully shows what I'm trying to achieve:
Base Case:
public class A {
// Contains default method implementations and properties
public virtual int someMethod(int i){
return i;
}
}
public class B: A{
// B does not inherit C
public override int someMethod(int i){
return i*base.someMethod(i);
}
}
public class C{
// Package class which B must subclass from
}
B Cannot Inherit from A and C:
public class A {
// Contains default method implementations and properties
public virtual int someMethod(int i){
return i;
}
}
public class B: C, A {
// Theoretically solves the problem, but C# doesn't support multiple inheritance with classes
public override int someMethod(int i){
return i*base.someMethod(i);
}
}
public class C{
// Package class which B must subclass from
}
Can't access default implementation in B, calling someMethod results in a stack overflow
public interface A {
// Contains default method implementations and properties
public virtual int someMethod(int i){
return i;
}
}
public class B: C, A {
// Making A an interface allows B to be stored in a list of type A, but how can I access the default implementation?
int A.someMethod(int i){
return i*(this as A).someMethod(i);
}
}
public class C{
// Package class which B must subclass from
}
Only working solution that I have, but seems very clunky:
public interface A {
// Contains default method implementations and properties
public virtual int someMethod(int i){
return _someMethod(i);
}
public virtual int _someMethod(int i){
return i;
}
}
public class B: C, A {
int A.someMethod(int i){
return i*(this as A)._someMethod(i);
}
}
public class C{
// Package class which B must subclass from
}
Is option 4 the best approach? Or is there a better way to do this?
Related
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.
I am trying to write a Fluent Interface API that can scale well. What structure would allow for strong types, inheritance, and state-full(as in the class type)?
For instance
class A
{
public A PerformFoo()
{
//do stuff
return this;
}
}
class B : A
{
}
I would like class B when calling PerformFoo to return B not A, ideally I would prefer to stay away from
public class B : A
{
public new B PerformFoo()
{
return (B)base.PerformFoo();
}
}
As to not have to override or new Every method in child classes. I believe I would need to use generics that use Type signatures.
I don't want to use extension methods but can't seem to get the structure right when doing it with casting (T) like in the answer for [a link]Fluent interfaces and inheritance in C#
If I understand correctly, the issue is that Method1 is not behaving the way you'd like, as it downcasts to A, preventing you from calling further methods. One way around this is to shadow the method in subclasses:
public class A
{
public A Method1()
{
return this;
}
}
public class B : A
{
public new B Method1()
{
return (B)base.Method1();
}
}
finally i figured out the structure
public class A {}
public class B : A {}
public class C<T> : A where T : C<T>
{/*most methods return T*/}
public class D:C<D>
{/*all methods return this*/}
public class E<T>:C<T> where T:E<T>
{/*all methods return T*/}
public class F:E<F>{}
now even specialized generics will still return the original caller
I have class A is super class, class B and C inherits A. Class A have method
public virtual GetName() {}
I want B can not override that method but C can do.
How can I do it?
PS: I got interview and they said they can do it but they didn't tell me how do that.
As written, the interview question was wrong: you can't (via simple, non-reflection means, at least) allow C to override that without allowing B to override it.
If C were in the same assembly as A, while B were in a separate one, you could create these rules by using an internal method:
public class A
{
public string GetName()
{
return GetNameInternal();
}
internal virtual string GetNameInternal()
{
return "A";
}
}
public class C : A
{
internal override string GetNameInternal()
{
return "C";
}
}
// in other assembly
public class B : A
{
// invalid due to scope:
//internal override string GetNameInternal() { ... }
}
It isn't possible in this scenario. The polymorphism (class inheritance) implies that the super class has no knowledge of who inherits itself, so your superclass cannot say "The ClassB cannot override this method but ClassC could" since it doesn't know their existence.
Maybe you misunderstood the question?
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();
}