I'm probably doing this totally wrong..
public class BaseClass
{
public string result { get; set; }
public BaseClass(){}
public BaseClass(string x) {
result = doThing(x);
}
public virtual string doThing(string x)
{
return x;
}
}
public class DerivedClass : BaseClass
{
public DerivedClass(){}
public DerivedClass(string x):base(x){}
public override string doThing(string x)
{
return "override" + x;
}
}
I'd like for a new DerivedClass("test") to have a result of "overridetest" but it doesn't: it calls the base method of doThing. Am I missing something? Do I need to make an AbstractClass and have both BaseClass and DerivedClass inherit from that, Derived class also overriding methods?
The problem is that you are making a virtual call in the constructor. The mechanics of this issue and possible workarounds are detailed here.
In short, the overridden function has not yet been constructed when you enter the constructor of the base class, therefore the virtual function in the base class is called.
You can't access a subclass' instance member from a base class.
It calls the base class's doThing method because that is the only available doThing method as far as the base class is concerned. If you want an instance of each class call it's own doThing method, in your child class replace:
public DerivedClass(string x):base(x){}
with:
public DerivedClass(string x)
{
doThing(x);
}
From a design perspective, you should always be wary of "doing things" during a constructor call. The purpose of a constructor is merely to get an instance of the class into a valid state for future use; it shouldn't try to "do" anything else or have any other side effects. If your object construction is a complicated affair, you might want to employ the Builder or Factory patterns to shield calling code from the complexity.
It's because your DerivedClass uses the base constructor and will set result as base.doThing("test") which is "test".
so you could change your DerivedClass to:
public class DerivedClass : BaseClass
{
public DerivedClass(){}
public DerivedClass(string x):base(x)
{
result="override"+x;
//or as result already be set as x, you can use: result="override" + result;
}
}
or as you said,
need to make an AbstractClass and have both BaseClass and
DerivedClass inherit from that, Derived class also overriding methods?
Related
I have a base class (can also be an interface) and n-classes that extend the base class.
I want to have a function that excepts only classes of the base class type.
Currently I am doing something like this
abstract class BaseClass{
public abstract void Execute();
}
class MyClass : BaseClass {
public void Execute(){
//my code
}
}
[...]
MyFunction(Type param)
{
//check if param is type of BaseClass. If not, throw exception
}
The problem with this implementation is, that I can pass any type of class. My goal is to prevent this.
Like in TypeScript you can do this
myFunction(param: {new (): BaseClass}){
//my code
}
Is there a similar approach I can use in C#?
There's a couple of things you can do, depending on what you actually want to do in the function.
Stating your actual use case makes it easier to come up with a solution.
Looking at the typescript code it looks like you want to be able to call the constructor inside the function to produce an instance of the given type that derives from BaseClass.
In this case I'd try using generics:
public void MyFunction<T>() where T: BaseClass, new()
{
T myClass = new T();
//Do stuff...
}
This works with interfaces/classes. It will only accept types deriving from BaseClass.
Edit: updated my answer after being notified how my previous answer wouldn't know if it was a grandchild of the base class
public abstract class BaseClass
{
public abstract void Test();
}
public class DerivedFromBase : BaseClass
{
public override void Test(){}
}
public class Grandchild : DerivedFromBase
{
}
public class Main
{
Grandchild aClass= new Grandchild(); // Instantiate Normally
UseIfOnlyTypeOfBaseClass(aClass);// Use Method with check like this
}
private void UseIfOnlyTypeOfBaseClass<T>(T param)
{
if (typeof(T).IsSubclassOf(typeof(BaseClass)))
{
Console.WriteLine("Match");
}
}
I've been reading about Polymorphism and I've been through something interesting.
I have created two classes: a super class and a derived class. As you can see derived class inherits from the super class and using its method.
In the derived class I have overridden the method of super class.
So my question is: I want to call the super class method from an object of a derived class
For example:
derivedClass a = new derivedClass()
a.method();
I want a.methood() to execute the superclass method.
Is that possible?
Summing up your question: You have a base class and a derived class. The derived class overrides a virtual method of the base class. Given an instance of the derived class, is it possible to force a call to the base class version of the method, instead of the derived class?
Short answer: From inside the class, yes. From outside the class, no.
Essentially what you wish to do here is a non virtual call to a virtual method. It is legal to do a non-virtual call to a base class method, but only from inside the class:
class B
{
public virtual void M() { Console.WriteLine("B.M"); }
}
class D : B
{
public override void M() { Console.WriteLine("D.M"); }
public void BM() { base.M(); }
}
...
D d = new D();
d.M(); // D.M
d.BM(); // B.M
Now, for advanced players there are sneaky ways to call B.M with an instance of D as the receiver, and I'm not going to tell you what they are. You should not attempt to do so. The CLR may flag such attempts as violations of its "verified code" rules. The rules of virtual overriding are there for your convenience and safety. Do not attempt to do an end-run around those rules.
From outside the derived class it is not possible. From within the derived class it is.
If you have these classes defined:
class A
{
public virtual void Method1() { Console.WriteLine("A"); }
}
class B : A
{
override public void Method1() { Console.WriteLine("B"); }
public void BaseMethod1() { base.Method1(); }
}
You can execute the following:
B b = new B();
b.Method1(); //Outputs "B"
b.BaseMethod1(); //Outputs "A"
((A)b).Method1(); //***Outputs "B" (even though you cast it as A)
If you change overide to new then the output of the last line is "A"
You can try calling base method as per your requirement, if there is some condition, according to which you want to call it, you can use that condition as well.
public class SubClass : SuperClass
{
public bool IsCallBaseClassMethod { get; set; }
public override void Method(){
if (IsCallBaseClassMethod)
{
base.Method();
}
}
}
Set the condition according to your requirement for the object and call the method for same object.
SubClass testObject = new SubClass();
testObject.IsCallBaseClassMethod = true;
testObject.Method();
Ok, I have a number of different classes deriving from a base class.
This base class is an abstract containing commom methods.
One of the methods is a Copy method, wich should be present in all derived classes, so, I've put it in the base class.
BUT, I want it to return the derived type not the base nor object.
The solution I got for that, is using a type paramter:
abstract class CopyableClass<T>
{
public abstract T Copy();
}
class DerivedClass : CopyableClass<DerivedClass>
{
public override DerivedClass Copy()
{
//do what is needed for copy and return a new DerivedClass
}
}
So, the main purpose here is to
Remove the type parameter in the base class and still make the method return the corresponding derived type.
One workaround.
The best thing I could do so far is one of the comments below, but it still uses a generic parameter
abstract class BaseClass
{
//base methods not related to deriving type
}
interface ICopyable<T>
{
T Copy();
}
class DerivedClass : BaseClass, ICopyable<DerivedClass>
{
public DerivedClass Copy()
{
//do what is needed for copy and return a new DerivedClass
}
}
You can't really. The base class can't possibly know all the future implementations. You'll have to resort to a generic abstract class (like you did) type or a generic Copy method.
public abstract class CopyableClass
{
public abstract T Copy<T>() where T : CopyableClass;
}
public class DerivedClass : CopyableClass
{
public override T Copy<T>()
{
if(typeof(T) != typeof(DerivedClass))
throw new ArgumentException();
// return your copy
}
}
Or, if you want to generalize the type check in your base class:
public abstract class CopyableClass
{
public T Copy<T>() where T : CopyableClass
{
if(GetType() != typeof(T))
throw new ArgumentException();
return (T) Copy();
}
protected abstract CopyableClass Copy();
}
public class DerivedClass : CopyableClass
{
protected override CopyableClass Copy()
{
return // Your copy;
}
}
Note that the second method puts alot of trust into the implementation of the derived class as it'll blindly cast the return value of the abstracted method. The compiler will let you return another type, implementing CopyableClass, in a derived type but it will be a runtime error. This is not a problem if you have the absolute control over all of the derived implementations (ie your abstract class also have an internal constructor).
This solution involves a middle class but I think its more inline with what the you are looking for. At least you get the possible benefit of isolating your copy code
public abstract class BaseClass
{
}
public abstract class CopyableClass<T> : BaseClass
where T: BaseClass, new()
{
public T Copy()
{
var copy = new T(); // Creating a new instance as proof of concept
return copy;
}
}
public class DerivedClass : CopyableClass<DerivedClass>
{
}
You actually want to implement copy in the base class and have it return T. This will make is so you call it with a type argument and it returns that type.
public static T Copy<T>() where T : CopyableClass
{
T retVal = new T();
// do whatever copying is required
return retVal;
}
To call it you do;
DerivedClass d = Copy<DerivedClass>();
Your code to actually do the copy might be a bit more work to make generic but it's worth the effort given you will have a single implementation of Copy() that works for any derived type. I don't know what logic belongs in the method so I've just stubbed things out. Also, I'd recommend checking out generics in general. They're often the best option for things like this. If your implementations need to be unique to the base class' keep the same method definition but make it abstract and then override it in the base classes.
This will allow you to case this base class to the derived type and return it.
public abstract class BaseClass<TDerived> : where TDerived: BaseClass<TDerived>
{
public TDerived DoSomethingCommon(string param)
{
var derivedType = (TElement)this;
//do something.
return derivedType;
}
}
Ok... in Objective C you can new up a subclass from a static method in the base class with 'new this()' because in a static method, 'this' refers to the class, not the instance. That was a pretty damn cool find when I first found it and I've used it often.
However, in C# that doesn't work. Damn!
So... anyone know how I can 'new' up a subclass from within a static base class method?
Something like this...
public class MyBaseClass{
string name;
public static Object GimmeOne(string name){
// What would I replace 'this' with in C#?
return new this(name);
}
public MyBaseClass(string name){
this.name = name;
}
}
// No need to write redundant constructors
public class SubClass1 : MyBaseClass{ }
public class SubClass2 : MyBaseClass{ }
public class SubClass3 : MyBaseClass{ }
SubClass1 foo = SubClass1.GimmeOne("I am Foo");
And yes, I know I can (and normally would) just use the constructors directly, but we have a specific need to call a shared member on the base class so that's why I'm asking. Again, Objective C let's me do this. Hoping C# does too.
So... any takers?
C# doesn't have any exact equivalent to that. However, you could potentially get around this by using generic type constraints like this:
public class MyBaseClass
{
public string Name { get; private set; }
public static T GimmeOne<T>(string name) where T : MyBaseClass, new()
{
return new T() { Name = name };
}
protected MyBaseClass()
{
}
protected MyBaseClass(string name)
{
this.Name = name;
}
}
The new() constraint says there is a parameterless constructor - which your didn't but we make it private to hide that from consumers. Then it could be invoked like this:
var foo = SubClass1.GimmeOne<SubClass1>("I am Foo");
Sorry, you can't do this. C# is morally opposed to static method inheritance. That GimmeOne method will never have any type other than MyBaseClass, and calling it from SubClass1 doesn't matter- it's still "really" a MyBaseClass call. The Reflection libraries could do this construction, but you'd never get anything other than a MyBaseClass out of it.
If you're calling a static method, presumably you know which subclass you're calling it from. Create a different factory method for each subclass. If you're actually trying to do this by instance, you should probably use a non-static virtual factory method (which will automatically call the most derived form of the function, which is probably what you want) instead.
As an abstract class cannot be instantiated, why is a constructor still allowed inside the abstract class?
public abstract class SomeClass
{
private string _label;
public SomeClass(string label)
{
_label=label;
}
}
Constructors of any derived class still have to call a constructor in the abstract class. If you don't specify any constructors at all, all derived classes will just have to use the default parameterless one supplied by the compiler.
It absolutely makes sense to have a constructor - but "public" is really equivalent to "protected" in this case.
Because you can still do the following:
public class SomeChildClass : SomeClass
{
public SomeChildClass(string label) : base(label){ }
public string GetLabel() { return _label; }
}
As you can see, the child class can call the base contructor (on the abstract class) to create an instance of itself.
Like Jon said though, public really isn't necessary. It's effectively the same as protected.