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).
Related
This question already has answers here:
Can a child class implement the same interface as its parent?
(5 answers)
Closed 3 years ago.
For example,I have a base class like this:
class Base: ICloneable
{
public object Clone()
{
//something
}
}
And is there any difference between these Derived classes?
class Derived: Base, ICloneable
{
//something
}
class Derived: Base
{
//something
}
Well, you may need to do it; here is a possible scenario:
When cloning, we usually want to return not universal object by cloned object type:
class Base {
// We can't declare this method as virtual: Derived class will return Derived
public Base Clone() {
...
}
}
...
Base test = new Base();
Base duplicate = test.Clone();
If we want to implement IClonable we have to do it explictly (in order to solve Clone() names conflict):
class Base : ICloneable {
public Base Clone() {
...
}
// This method is efficiently private, and that's why can't be virtual
object ICloneable.Clone() => Clone();
}
Now we want a Derived class which can be cloned as well:
class Derived : Base {
// Note that now we have new Clone method which returns Derived instance (not Base one)
public new Derived Clone() {
...
}
}
...
Derived test = new Derived();
Derived duplicate = test.Clone();
If we keep it like this then we'll have wrong behaviour:
Derived test = new Derived();
// This will be wrong:
// Base.ICloneable.Clone() will be called which executes "Base Clone()" method
// instead of expected "new Derived Clone()"
object clone = (test as IClonable).Clone();
So we have to reimplement IClonable interface:
class Derived : Base, ICloneable {
// Please, note that now we have new Clone method which returns Derived instance
public new Derived Clone() {
...
}
// This ICloneable implementation will call Derived Clone()
object ICloneable.Clone() => Clone();
}
...
// Derived ICloneable.Clone() will be called
// which executes "new Derived Clone()" method
object clone = (test as IClonable).Clone();
Actually, you can do this, if your derived class provides its own (explicit) implementation of the interface:
class B : A, Icloneable
{
object IClonable.Clone()
{
// do something completely new
}
}
As this is an explicit implementation, you have to cast your B-instance to the interface in order to call the new implementation. Otherwise the implementation from A is used (see my fiddle: https://dotnetfiddle.net/tuUnCm).
No, you do not have to implement the interface in the derived class. The derived class can also be cast as the interface type when the base class implements the interface. Like this:
public interface ISomething
{
void Say();
}
public abstract class BaseClass : ISomething
{
public void Say(string something)
{
Console.WriteLine("Say: " + something);
}
}
public class DerivedClass : BaseClass
{
}
var x = new DerivedClass() as ISomething;
x.Say("Derived");
If understanding the problem correctly, you don't need to inherit for base and ICloneable as base already inherits from it.
This is fine
class base:ICloneable
{
public object Clone()
{
//something
}
}
This is fine too, as derived1 will inherit ICloneable, as its part of your base class
class derived1:base
{
//something
}
However this is saying it will, inherit from base (which already inherits from ICloneable) AND ICloneable. Its redundant and defeats the purpose of having an interface.
class derived1:base,Icloneable
{
//something
}
Hope that helps!
No need, when your base class is implementing interface or other classes all the properties and functionality introduced in base class will inherit to derived class.
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.
I am having trouble overriding a method that returns a generic class that is strongly typed.
This is just setting up for the example below
public class Something : ISomething {}
public interface ISomething {}
My issue is with the Clone method below, only the second one works.
public class ClassA : AbstractClass<Something>
{
public override ClassA Clone() // <--- this doesn't work
{
return this; // this is just dummy code
}
public override AbstractClass<Something> Clone() // <-- this works
{
return this; // this is just dummy code
}
}
public abstract class AbstractClass<T> where T : ISomething
{
public abstract AbstractClass<T> Clone();
}
I would prefer to have the first Clone method, as the name of the class doesn't change. But only the second method compiles. Is there any way to avoid this?
The first override changes the actual signature:
Your method on the base class establishes that it will return an AbstractClass<T>.
Since your subclass says that T is going to be something, this now implies that the method returns an AbstractClass<Something>. While ClassA is an AbstractClass<Something> that doesn't mean that all AbstractClass<Something> are a ClassA.
Consider the following example:
AbstractClass<Something> myVar = new ClassA(); // works, because ClassA is an AbstractClass<Something>
// Now we hold a reference to an AbstractClass<Something>
myVar.Clone(); // => This should return an AbstractClass<Something> not ClassA
Extending the example: consider a ClassB:
public class ClassB : AbstractClass<Something> {}
Both ClassA and ClassB are AbstractClass<Something>. If we retake the first example:
AbstractClass<Something> myVar;
myVar = new ClassA();
myVar = new ClassB();
// Here you don't know whether it's a ClassA or ClassB, you only know it's an `AbstractClass<Something>`
myVar.Clone();
You could add another generic parameter for the return type:
public abstract class AbstractClass<TC, T> where TC: AbstractClass<TC, T> where T : ISomething
{
public abstract TC Clone();
}
then change ClassA to:
public class ClassA : AbstractClass<ClassA, Something>
{
public override ClassA Clone()
{
return this;
}
}
It is impossible to change the return type while overriding a method.
You could remove the override from the first implementation, and this will define a new method. But, because you have that abstract Clone method in the base class, you are forced to implement it as well, and you'll end up with 2 methods with the same name, and the same parameters, so the code will not compile.
Do you really need that Clone method in the abstract class ?
I think you should remove the Clone method from the abstract class, and add the Clone method in the derived class (perhaps also implementing ICloneable interface).
If I am using shadowing and if I want to access base class method with derived class objects, how can I access it?
Use the base keyword:
base.MethodOnBaseClass();
The base keyword is used to access members of the base class from within a derived class:
First cast the derived class object to base class type and if you call method it invokes base class method. Keep in mind it works only when derived class method is shadowed.
For Example,
Observe the commented lines below:
public class BaseClass
{
public void Method1()
{
string a = "Base method";
}
}
public class DerivedClass : BaseClass
{
public new void Method1()
{
string a = "Derived Method";
}
}
public class TestApp
{
public static void main()
{
DerivedClass derivedObj = new DerivedClass();
BaseClass obj2 = (BaseClass)derivedObj; // cast to base class
obj2.Method1(); // invokes Baseclass method
}
}
You qualify the method call:
base.foo();
DerivedClass derivedObj = new DerivedClass();
(derivedObj as BaseClass).Method1(); // cast to base class with method invoke
I create base generic class with no fields with just one method
public class Base<T> where T:class
{
public static T Create()
{
// create T somehow
}
}
public class Derived1 : Base<Derived1>
{
}
public class Derived2 : Base<Derived2>
{
}
public class Program
{
bool SomeFunction()
{
// Here I need reference to base class
Base baseref; // error here
switch(somecondition)
{
case 1:
baseref = Derived1.Create();
break;
case 2:
baseref = Derived1.Create();
break
}
// pass baseref somewhere
}
}
An obvious option would be converting base class to interface, but this is not possible because interface cannot contain static methods.
I think I need some intermediate base class. Please suggest
You must remove the generic parameter from the Base class, you can move it to just the Create method:
public class Base
{
public static T Create<T>() where T : class
{
return Activator.CreateInstance<T>();
}
}
public class Derived1 : Base
{
}
public class Derived2 : Base
{
}
Preliminary Assessment
With this statement,
public class Derived1 : Base<Derived1> {
you're using Derived1 in two different ways according to the base class.
You're effectively telling the C# compiler that Derived1 both:
inherits Base
and Base uses instances of Derived1 through non-inheritance means.
This is not wrong (if that's what you really want), but it's unusual for most programming scenarios; you normally choose one or the other. However the benefit of your logic is: not only do you have an implicit instance of Derived1 through inheritance (same for any other derived class), but the base class can also handle other external instances of that same derived type through the type parameter <T>
One problem I see in the Base class is it turns into a kind of circular scenario when using the factory method as intended, because, to support all derived classes it would need to support something like class Base<T> where T:Base<T>. That's next to impossible to declare because you would have to say in a circular fashion: Base<Base<Base<!!!>>> baseref = null; where !!! represents an infinite number of the same.
One Solution...
One possible (and strong solution) is to move the Type parameter from the class to the factory Create method and restrict its usage to the Base class type like so:
using System;
public abstract class Base
{
public static T Create<T>() where T : Base
{
return Activator.CreateInstance<T>();
}
}
Note: I have made the base class abstract which restricts instantiation to the derived types; however you can still use base class references (see switch statement usage below).
These derived classes still inherit from base.
public class Derived1 : Base
{
}
public class Derived2 : Base
{
}
Your factory method is restricted to create only instances of derived types. The logic has been swapped around so the derived type is given to the factory method instead of the factory method being called on it.
public class Program
{
bool SomeFunction()
{
Base baseref = null;
switch(DateTime.Now.Second)
{
case 1:
baseref = Base.Create<Derived1>(); // OK
break;
case 2:
baseref = Base.Create<Derived2>(); //OK
break;
case 60:
baseref = Base.Create<string>(); //COMPILE ERR - good because string is not a derived class
break;
}
// pass baseref somewhere
}
}
public abstract class Base
{
}
public class Base<T> : Base where T : class
{
public static T Create()
{
// create T somehow
}
}
public class Derived1 : Base<Derived1> // also inherits non-generic Base type
{
}
public class Derived2 : Base<Derived2> // also inherits non-generic Base type
{
}
How about creating an interface and having the abstract class implement the interface?