When a child class inherits from both a parent class and an interface, why can the child class not access a parent class method?
Consider the following, where I can't access the DoSomething() method.
class Program
{
static void Main(string[] args)
{
IMyInterface myClass = null;
myClass = new ChildClass();
// this returns error
myClass.DoSomething();
}
}
internal class ParentClass
{
public ParentClass() { }
public void DoSomething() { }
}
internal class ChildClass : ParentClass, IMyInterface
{
public string MyProperty { get; set; }
public ChildClass() : base() { }
}
internal interface IMyInterface
{
string MyProperty { get; set; }
}
I've looked through SO discussions here and here, but they seem to focus on how a member is hidden using new, override, and virtual keywords... sorry, but I can't figure out how that applies to this situation. Also, I've browsed through the MSDN API reference on interfaces here and here, with no luck.
The problem here is specifically to do with the declaration of the variable in your Main method.
IMyInterface myClass = null;
myClass = new ChildClass();
// this returns error
myClass.DoSomething();
Taking lines in isolation, we can reduce it to just this.
IMyInterface myClass = null;
// BLAH BLAH myClass gets initialized somehow, we don't know/care how.
myClass.DoSomething();
So at that point, we only know we have an initialized object of interface IMyInterface. In other words, taking that line alone, we don't know that it's a ChildClass. The only known method of IMyInterface is MyProperty, so that's the only thing we know is available to us.
You could fix this by declaring myClass specifically as a ChildClass instance. You can even return this variable in a method that expects to return an IMyInterface type.
This does not work for a very straightforward reason:
IMyInterface does not have a DoSomething method.
If you modify your interface as follows, your code will work.
internal interface IMyInterface
{
string MyProperty { get; set; }
void DoSomething();
}
DoSomething() is from ParentClass, and you are using an IMyInterface reference.
To use this method, you need to do a cast:
((ChildClass) myClass).DoSomething();
or
((ParentClass) myClass).DoSomething();
Because the type of myClass is IMyInterface:
IMyInterface myClass = null;
and IMyInterface doesn't have a DoSomething() method:
internal interface IMyInterface
{
string MyProperty { get; set; }
}
However, with polymorphism the type cal also be ParentClass or ChildClass. So you can use the method by morphing the type:
(myClass as ChildClass).DoSomething();
As with any time you cast or morph the type of an object, be careful for nulls. If the type can't be converted then myClass as ChildClass would be null, so the above would result in a NullReferenceException.
The best way to understand this is to know the difference between an interface and a parent/child class.
An interface is a contract that can exist on any class regardless of it's inheritance chain. You could put that interface on a class that doesn't inherit from ParentClass, and all that class has to fulfill is what is in your interface (in your case, the MyProperty property). If you added DoSomething() to the interface, this class would then also be required to have that method.
A subclass (child class) inheriting from a parent class has established a relationship. The parent class shares it's non-private methods/properties/member subset with it's child class. Therefore, you can cast a child class to it's parent class and retain accessibility to those properties.
Related
public abstract class Base
{
public Base ClassReturn()
{
return this;
}
}
Is there possibility to return child type that invoked ClassReturn method?
I've done that in extension method:
public static T ClassReturn<T>(this T obj) where T : Base
{
return (T) obj.ClassReturn();
}
But I want to embeed it in Base class instead of extension method. Is there possibility to do that with generics?
I will copy my comment which describes what I want to achieve:
I need something similiar to builder pattern and I have different
classes that depending on previous operations do something else, now I
want to have a similiar functionality in every of them and when I use
it I lose object type. So my solution is either implement that
functionality multiple times in every class or create extension
method. But I always thought when it is possible to make extension
method for class then I can embeed that in class, but as I see it is
not possible.
Full example:
public class Child1 : Base
{
public Child1 Operation1()
{
Console.WriteLine("operation1");
return this;
}
}
public class Child2 : Base
{
public Child2 Operation2()
{
Console.WriteLine("operation2");
return this;
}
}
static void Main(string[] args)
{
Child1 ch = new Child1();
ch.Operation1().Operation1().ClassReturn().Operation1()
}
I can't use Operation1 after ClassReturn if I don't use extension method.
Try this one:
public abstract class Base<T> where T: Base<T>
{
public T ClassReturn
{
get { return (T)this; }
}
}
public class Child1 : Base<Child1>
{
}
public class Child2 : Base<Child2>
{
}
From your question and your comments, what you are trying to achieve is not possible directly from the type system. By returning an instance of Base you are specifically saying that all you are interested is that you have something that derives from Base, but that the specific class doesn't matter. Statically, the compiler no longer has the information it needs to perform a cast.
If you are trying to get the original type back statically, then you have to supply the information to the compiler, and in this case you can't guarantee that you have the correct information. In the example below, the instance is created from derived type A but attempted to be cast to derived type B through the extension, the compiler will allow the code to compile, but you'll get an exception at runtime.
public class A : Base { }
public class B : Base { }
public static class BaseExtensions
{
public static T GetAsT<T>(this Base base) where T: Base
{
return (T)base;
}
}
public static void Main()
{
Base obj = new A();
B b = obj.BaseAsT<B>(); // This compiles but causes an exception
}
You should look up the Liscov Substitution Principle to get information on how to properly work with base and derived classes in the system as a whole, and then write up a question dealing specifically with the result you are trying to achieve.
I have a base class and an interface. Now I am creating a subclass from these. If I create a reference variable of the interface type to point to an object of the child class, can I access the base class methods using it?
Class BaseClass
{
public void baseClassMethod()
{
.....
}
}
Interface MyInterface
{
public void Interfacemethod();
}
Class ChildClass:BaseClass, MyInterface
{
....
}
....
main()
{
MyInterface myclass= new ChildClass ();
myclass.baseClassMethod();//Is this possible? y?
}
The variable myclass is statically typed as MyInterface, which does not have a method called baseClassMethod() - so no, that won't work. You would need to cast the reference back to BaseClasss or Child (either would be fine), or add the method to MyInterface (or some additional interface).
I have 2 classes:
public class Class1
{
private string Name1;
public Class1()
{
//How to get Name2 of the derived class?
}
}
public class Class2 : Class1
{
private string Name2 = "asd";
public Class2(){}
}
How to get Name2 of the derived class in the base constructor?
public class Class1
{
private string Name1;
public Class1()
{
class2 xxx = this as class2
if (class2 != null)
this.Name1 = xxx.Name2;
}
}
"this as class2" - is not null
This example is correct. The only thing is I don't know Derived class is Class2 or class3 or class4 .... I need universal code
You cannot (and more importantly, you should not) do that. When you are in the constructor of the base class, the subclass portion has not been initialized yet, so there is no way to get to the members of the subclass: quite simply, they do not exist yet.
Another problem is that the Name2 attribute may not be present in a subclass at all, even at the level fo the definition: I can derive Class3 from Class1, and give it Name3 attribute instead of Name2.
All this does not touch on such "insignificant" matters as breaking encapsulation: Name2 is a private member, which may be removed in the future implementations of the Class2.
The only way for the subclass to communicate things to superclass in a constructor is passing parameters. This would work:
public class Class1 {
private string Name1;
public Class1(string subclassName2)
{
// Subclass has passed its Name2 here
}
}
public class Class2: class1 {
private string Name2;
public Class2(string myName) : base(myName) {
Name2 = myName;
}
}
You can access the code in the derived class from the base class code, but only from within an object which is actually a derived class object, and then only if the methods involved are virtual methods.
If you have an object which is itself an instance of the base class, then from within that instance you cannot see derived class code from the base class .
example
public class Baseclass{
public void Foo()
{
Bar();
}
public virtual void Bar()
{
print("I'm a BaseClass");}}
public classs Derived: BaseClass{
public override void Bar()
{
print("I'm a Derived Class");}}
Main()
var b = new BaseClass();
x.Foo() // prints "I'm a BaseClass"
// This Foo() calls Bar() in base class
var d = new Derived();
d.Foo() // prints "I'm a Derived Class"
// in above, the code for Foo() (in BaseClass)
// is accessing Bar() in derived class
I think you could not because when you instantiate derived class, base class constructor is called first to initialize base class and then the derived class is initialized.Within the base class constructor there is no way to access derived class members because they are not available at that time.
You cannot do it. It strictly violates the Object Oriented Approach programming ground rules.
As each instance of Class2 will have the Name2 property. But the same cannot be guaranteed for instance of object for Class1.
It's not really clear what you're trying to achieve. It is possible to do the following, but I don't think it's good practice:
interface IHasName2
{
string Name2 { get; }
}
class Class1
{
string Name1;
public Class1()
{
var withName2 = this as IHasName2;
if (withName2 != null)
{
Name1 = withName2.Name2;
}
}
}
Then classes deriving from Class1 may implement IHasName2 if they like.
But maybe you want an abstract class to make sure derived classes specify a Name2. It could be like this:
abstract class Class1
{
string Name1;
// instance property required to be implemented by deriving classes
protected abstract string Name2 { get; }
// instance constructor
protected Class1()
{
// 'Name2' can be read already here (dangerous?)
Name1 = Name2;
}
}
Finally, consider the simple solution proposed by dasblinkenlight to have the instance constructors of Class1 take in a string parameter for the name. Deriving classes would then have to supply that name parameter when they "chain" their base class constructor.
I have the following class hierarchy:
public abstract class BaseClass : IBaseInterface
{
public int PropertyA{
get
{
return this.propertyA;
}
set
{
this.propertyA = value;
// ... some additional processing ...
}
}
}
DerivedClassB : BaseClass
{
// some other fields
}
public class ContainingClassC
{
public IBaseInterface BaseInterfaceObjectD
{
get;
set;
}
}
Now, in order to access PropertyA of a DerivedClassB-Object (inherited from BaseClass), I have to cast the object to BaseClassA's ancestor, like so:
// This ContainingClassC is returned from a static, enum-like class:
// containingObject.PropertyA is DerivedClassB by default.
ContainingClassC containingObject = new ContainingClassC();
((IBaseInterface)containingObject.BaseInterfaceObjectD).PropertyA = 42;
Is there a way I can restructure these classes to do away with the cast? This code is part of a library, and my colleague wants me to get rid of the cast.
The goal is to simply write containingObject.BaseInterfaceObjectD.PropertyA = 42.
First of all in the line ((IBaseInterface)containingObject.BaseInterfaceObjectD).PropertyA = 42; you are casting the member to the same type that it is declared in, so the casting doesn't actually do anything.
To be able to access the PropertyA in the derived class - since you are casting it to an interface - the property must be declared in the interface and then implemented in the BaseClass.
public interface IBaseInterface{
int PropertyA{get;set;}
}
public abstract class BaseClass : IBaseInterface{
public int PropertyA{
get{ return this.propertyA;}
set {this.propertyA = value;}
}
}
As long as the interface is implemented properly, ProprtyA should be available in the base class, the derived class or with either of them cast'ed to the interface type.
If it's just a problem of the property not showing up in IntelliSense, then it might be a problem with your settings. Check out Options->Text Editor->C# and make sure you have IntelliSense turned on and not set to hiding anythig.
are the two methods in the class "Confused" below the same?
class MyClass
{
public override string ToString()
{
return "I am confused now";
}
}
class Confused
{
public MyClass GetMyClass()
{
return new MyClass();
}
public T GetMyClass<T>() where T : MyClass, new()
{
return System.Activator.CreateInstance<T>();
}
}
class Program
{
static void Main()
{
Confused c = new Confused();
System.Console.WriteLine(c.GetMyClass());
System.Console.WriteLine(c.GetMyClass<MyClass>());
}
}
They produce different IL, but is there any reason to write the generic version other than the 'straight up' version other than to confuse the heck out of collegues :)
If you write the generic version, you can instantiate and return derived classes:
where T : MyClass
Also, with the generic version you don't need the activation code:
return new T();
This is because you have specified:
where T : new()
The generic constraint enforcing a public parameterless constructor.
Sure there's a difference. Let's say you have a second class deriving from MyClass:
class MyClass2 : MyClass { }
Then you can do
MyClass2 myClass2 = confused.GetMyClass<MyClass2>();
You can't do that with the other function.
MyClass could be a base class (or an interface IMyClass). The generic version with the constraint says you want this function to work for any class derived from (or implementing) a common base or interface and to return the result as that derived class, not as the base.
class MyClass { }
class MySpecializedClass : MyClass { }
// etc.
There is a very big difference:
The non generic version can only return instances of type MyClass, whereas the generic version can return instances of type MyClass and all classes derived from MyClass!
No. They are not the same. The first will only ever construct a MyClass object, and the second will construct any object that is a MyClass or a descendent of MyClass, based on the type parameter.
They would give the same result ONLY if you called .GetMyClass<MyClass>(). However, I presume the extra method has been created to allow for creation of other classes? If not, then they're the same, so one's redundant (and I'd get rid of the generic version as has overhead inside the assembly).
Are they being used differently?
They are not the same. The generic allows inherited classes to be built as well like this:
class MyClass
{
public override string ToString()
{
return "I am confused now";
}
}
class InheritedClass : MyClass
{
}
class Confused
{
public MyClass GetMyClass()
{
return new MyClass();
}
public T GetMyClass<T>() where T : MyClass, new()
{
return System.Activator.CreateInstance<T>();
}
}
class Program
{
static void Main()
{
Confused c = new Confused();
System.Console.WriteLine(c.GetMyClass());
System.Console.WriteLine(c.GetMyClass<MyClass>());
System.Console.WriteLine(c.GetMyClass<InheritedClass>());
}
}
I'm not quite sure, but Generics are a runtime feature in .NET. Therefore, the non-generic method isn't equivalent to the generic one, even though it is used equivalently. As they're public, this can't be optimized away.