My problem is as follows:
I have a base class that needs to be abstract. It has several derived classes, each with their own special properties that are contained in the Properties member.
I need to be able to create a new instance of one of these derived classes, so that all the members are equivalent but modifying the new instance doesn't modify the original.
Finally, I want to do it without having to hardcode in every derived type of the base class. (Which would, admittedly, be the easiest solution, however that isn't the point)
All the derived classes satisfy an "is-a" relationship to the base class.
Here is the code:
public abstract class BaseClass
{
//Default properties here
int x, y, z, ...;
//Custom made class to hold custom properties
protected Attributes Properties;
public BaseClass createNewInstance()
{
return createNewInstanceStep1();
}
//Each derived class implements their own version of this,
//to handle copying any custom members contained in Properties.
protected abstract BaseClass createNewInstanceStep2();
protected BaseClass createNewInstanceStep1()
{
BaseClass newInstance = new BaseClass(); // <- Doesn't work because class is abstract
//Copy default properties
newInstance.x = x;
newInstance.y = y;
newInstance.z = z;
//Call the new instance's step 2 method, and return the result.
return newInstance.createNewInstanceStep2();
}
}
The issue with this code is the BaseClass newKeyFrame = new BaseClass(); line. As the class is abstract, you cannot create an instance of it.
The problem is that I need to be able to call the constructor of whatever type the derived class is, as they all have different code in their constructors that cannot be shared.
I've heard that using Reflection might be a viable solution, however I have no idea how.
How can I solve this without having to hardcode in a case for every derived type?
You could make createNewInstanceStep1 generic. I've also modified the Step2 to be type void (I'm expecting it to modify the current instance, so the return would always be return this; anyway), because otherwise it doesn't really make sense the way I'd like to use it here. If it doesn't make sense to change it like this, then my whole approach of only making this method generic won't work.
And createNewInstance now uses reflection to call the equivalent of return createNewInstanceStep1<this.GetType()>();.
public BaseClass createNewInstance()
{
var method = typeof(BaseClass).GetMethod("createNewInstanceStep1", BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(this.GetType());
var value = method.Invoke(this, null);
return (BaseClass)value;
}
//Each derived class implements their own version of this,
//to handle copying any custom members contained in Properties.
protected abstract void createNewInstanceStep2();
protected T createNewInstanceStep1<T>() where T : BaseClass, new()
{
T newInstance = new T(); // works!
//Copy default properties
newInstance.x = x;
newInstance.y = y;
newInstance.z = z;
//Call the new instance's step 2 method, and return the result.
newInstance.createNewInstanceStep2();
return newInstance;
}
If this won't work, another approach is a self-referential generic type. It's good to avoid this, though, because it's confusing and overall not a good design.
public sealed class SubClass : BaseClass<SubClass>
{
protected override SubClass createNewInstanceStep2()
{
Console.WriteLine("In step 2");
return this;
}
}
public abstract class BaseClass<T> where T : BaseClass<T>, new()
public T createNewInstance()
{
return createNewInstanceStep1();
}
//Each derived class implements their own version of this,
//to handle copying any custom members contained in Properties.
protected abstract T createNewInstanceStep2();
protected T createNewInstanceStep1()
{
T newInstance = new T();
...
What's the problem with letting the derived classes do the instantiation of the new instance?
public abstract class BaseClass
{
//Default properties here
int x, y, z, ...;
//Custom made class to hold custom properties
protected Attributes Properties;
public abstract BaseClass createNewInstance();
protected void CopyData(BaseClass original)
{
this.x = original.x;
this.y = original.y;
this.z = original.z;
}
}
public class ChildClass : BaseClass
{
public BaseClass createNewInstance()
{
ChildClass newInstance = new ChildClass();
newInstance.CopyData(this);
// Do any additional copying
return newInstance;
}
}
You can make createNewInstanceStep1 a protected void init method that initiates this object, and call it in each subclass's constructor.
How are you going to know what type of instance to create? If you'll have an existing instance of the derived class and want to create another instance which is basically identical to it, you should have your base type implement a protected virtual CloneBase method which calls MemberwiseClone and does any deep copying the base type knows about, and a public Clone method which chains to CloneBase and casts to the base type. Each derived types should override CloneBase to chain to base.CloneBase and add any necessary additional deep copying (that step may be omitted if no additional deep-copy logic is required), and also shadow the public Clone method with one that chains to CloneBase and casts the result to its type [using a separate CloneBase makes it possible to both declare a new Clone method with a different signature while also overriding and chaining to the base-class method].
If you'll have an existing instance of the new class, but want its properties to be copied from some other instance, could have an abstract ConstructInstanceLike(x) method which each derived type would implement to either call one of its constructors, or clone itself and modify the clone to match the passed-in object. Neither approach is terribly elegant, but either can work.
If you won't have an existing instance of the new class, you'll need some other means of getting something of the appropriate type. The nicest approach is probably to store a collection of Func<TParams, TResult> delegates, one for each derived type of interest, and then invoke one of those functions to generate an object of one of the associated derived type. It would also be possible to define an interface
IFactory<TParam, TResult> { TResult Create(TParams param); }
but in many cases a delegate will be more convenient to work with.
Related
I was practicing inheritance, using a test program in C# and I found out that the following statement does not throw an error:
BaseClass baseObj = new DerivedClass();
Why is this statement allowed and is there a situation where this statement would be useful to a programmer?
Here is my test program:
class BaseClass
{
public void show()
{
Console.WriteLine("Base Class!");
}
}
class DerivedClass : BaseClass
{
public void Display()
{
Console.WriteLine("Derived Class!");
}
}
class Result
{
public static void Main()
{
BaseClass baseObj = new DerivedClass();
baseObj.show();
}
}
I recommend you read about inheritance and Polymorphism in more detail. (here and here)
In this answer I try to keep concepts simple enough.
Why is this statement allowed and is there a situation where this
statement would be useful to a programmer?
But in order to explain your question a bit lets take a look at simple and classic example of object oriented program that needs to use polymorphism.
Assume you are writing a program that needs to store some shapes and display them on screen. To achieve this you need to store all shapes in an array for example. right?
Suppose our classes are something like these:
class BaseShape
{
public virtual void Display()
{
Console.WriteLine("Displaying Base Class!");
}
}
class Circle : BaseShape
{
public override void Display()
{
Console.WriteLine("Displaying Circle Class!");
}
}
class Rectangle : BaseShape
{
public override void Display()
{
Console.WriteLine("Displaying Rectangle Class!");
}
}
And your array can be object array. like this:
object[] shapes = new object[10];
In your application you need to write a method to display shapes.
One solution can be iterating over all shapes and call right method of exact type of shape. like this:
public static void DisplayShapes_BAD(){
foreach(var item in Shapes)
{
if(typeof(Circle) == item.GetType())
{
((Circle)item).Display();
}
if(typeof(Rectangle) == item.GetType())
{
((Rectangle)item).Display();
}
}
}
But what happens when another type of Shape appears in application? Basically you need to modify DisplayShapes_BAD() method to support new type of Shape (add new if statement to body of method)
This way you break Open/Closed principle of object oriented programming. and your code is not much maintainable.
Better way to store shapes to avoid this bad method is to use array of BaseShape. like this:
public static List<BaseShape> Shapes = new List<BaseShape>();
Here is how to add item to this list of shapes:
Shapes.Add(new Circle());
Shapes.Add(new Rectangle());
Now take a look at good implementation of DisplayShapes method.
public static void DisplayShapes_GOOD()
{
foreach(var item in Shapes)
{
item.Display();
}
}
In above method we call Display method on item with type of BaseShape. But how C# knows to call right method (for example circle display or rectangle display). This mechanism is Polymorphism.
Complete Code shared as Gist.
As per my understanding in java,You are trying to call object of DerivedClass by using BaseClass reference varibale baseobj and this coding scenario is totally valid because it is providing the facility of runtime polymorphism.
Before runtime polymorphism lets understand the Upcasting. When reference variable of parent class is used to refer the object of child class then it is called as Upcasting
class A{}
class B extends A{}
A obj= new B // Upcasting.
Runtime Polymorphism is a process in which a call to an overridden method is resolved at runtime rather than compile-time.
Since you are not overriding show method in derived class,You are not doing runtime polymorphism but simply upcasting and upcasting is useful when we want to resolve the calling to overridden method at runntime.
First off, the question why it's allowed, is simply because an instance of the derived class is an instance of the base class (subtype polymorphism). Same goes for being able to assign any derived class to an object variable: all .net classes derive from object in the end, so you could also have done object baseObj = new DerivedClass().
The goal of the type that is used for the declaration is to indicate which type of interface is being worked with (intent). If you would declare the variable as object, you'd say that only the reference is important. If you declare as BaseClass, you say that you are using an object where the properties and methods of BaseClass are important. By using BaseClass baseObj = new DerivedClass(), you are saying you need the BaseClass functionality, but are using a DerivedClass instance to define the workings of the mapping described in BaseClass.
One reason for this could be that BaseClass is abstract (BaseClasses often are), you want a BaseClass and need a derived type to initiate an instance and the choice of which derived type should be meaningful to the type of implementation.
A reason for which it's even more often used, is because at any time, another class deriving from BaseClass can be assigned to the same variable. Consider:
BaseClass baseObj = SomeCriterium ? (BaseClass)new DerivedClass() : new AlternateDerivedClass();
The scope of the variable in the example is only in the main method, but if it were anywhere in the class, or it could be changed through a property or otherwise, by using BaseClass, anyone using your class could assign other BaseClass (derived) instance, instead of only DerivedClass (derived) instances.
Finally an example for reassigning, using an interface declaration (as far as polymorphism is concerned, the same can be applied to declaring an implemented interface instead of the class as it can to a baseclass):
IEnumerable<T> values = new List<T>();
if(needfilter)
values = values.Where(el => filtercriterium);
If values was declared as a List, the values variable could not be reused for the filtered enumeration. Basically first you say that you need the values variable only for enumeration. After that you can reassign values with another enumeration instead of only with a list.
When we want to control instantiation of objects, we often make the constructor private or internal:
public class A {
private A(int aParam) { }
}
However, this is essentially the same as sealing the class 'A' because now no one can inherit from it.
So, we can make the constructor protected:
public class A {
protected A(int aParam) { }
}
public class B {
protected B(int aParam) : base(aParam) { }
}
However, this means that any code from B (or any class derived from it) can instantiate a new A.
I am looking for a way to control instantiation but without having to make classes sealed (effectively or otherwise).
Note: I know that classes can always be instantiated with reflection and other tricks anyway; I'm only interested in creating an explicit 'contract'. If someone wants to subvert my contract deliberately that's up to them.
I am looking for a way to control instantiation but without having to make classes sealed (effectively or otherwise).
This is really contradictory in your requirements.
If you want to allow subclasses to be created, you must allow the subclass to effectively create the parent, which means you need to have, at a minimum, one protected constructor. Without this, there would be no way for the subclass to initialize the instance properly.
By exposing a constructor as protected, you allow subclasses to change the instantiation rules (they can always add a public constructor).
There are really only two options here:
Make the constructor protected, and assume that the subclass will do the "right thing" (whatever that is in your scenario), or
Seal your class, and then expose the construction method you choose. This prevents subclasses, but does not prevent your class from being reused via composition instead of inheritance.
Am not sure what you mean. If am not wrong then you're trying to prevent instantiation of Base Class from Derived Class Right?
That is the default behavior too. You cannot instantiate base class from derived class when your base class constructor is protected.
class Program
{
A a = A.CreateInstance();//works
B b = B.CreateInstanceOfB();//works
A ab = B.CreateInstanceOfA();//wont work
}
public class A
{
protected A()
{
}
public static A CreateInstance()
{
return new A();
}
}
public class B : A
{
protected B()
: base()//
{
}
public static B CreateInstanceOfB()
{
return new B();
}
public static A CreateInstanceOfA()
{
return new A();//This wont compile CS1540: Cannot access protected member...
}
}
Protected constructor is intended to invoke through constructor chaining(using base keyword) only. You can't instantiate it without reflection.
Hope this helps.
If you want to be able to instantiate subclasses, but prohibit explicit instantiation of a base class, then you have two options:
Add a pure virtual method thus making the base class abstract.
Add a protected constructor, and overload the "new" operator to disallow explicit instantiation of the base class, even though it's not abstract.
I'm trying to create a set of classes with different level of abstraction. I will use the Vector example here.
My goal is that the user of my classes can choose the level of abstraction to use i.e. they may or may not want to be using the more derived class.
interface IVector
{
Vector A();
}
interface ISparseVector : IVector
{
new SparseVector A();
}
Now, I implement the classes as such:
class Vector : IVector
{
public Vector A() { return new Vector(); }
}
class SparseVector : Vector,ISparseVector
{
public new SparseVector A() { return new SparseVector(); }
}
This is all fine and dandy. However, when the base class is abstract such as:
abstract class Vector : IVector
{
public abstract Vector A();
}
class SparseVector : Vector,ISparseVector
{
public SparseVector A() { return new SparseVector(); } // Hides abstract member.
}
I get a compile error saying that the derived method is hiding the abstract method in Vector. Any idea of how to get around this?
The feature you want is called "return type covariance", and it is not a feature of C#. Return type covariance is the feature where you can have a virtual method that return an Animal, and then you override that with a method that returns a Giraffe.
Doing so is typesafe and some languages do have this feature -- C++ for example -- but C# does not and we have no plans to add it. Your overriding method has to be marked override, and it has to match exactly -- in name, formal parameter types, and return type.
The reason is in your first example on the Vector class, you weren't specifying an access level for the A() method. This means it is a private method, which is the default. You could use the new keyword in the SparseVector class to get around this error.
For a start, you should look at this thread which specifies why you cannot have an abstract constructor.
Why can't I create an abstract constructor on an abstract C# class?
Then, you should put an abstract method in your Vector class that can actually be overridden to provide implementation, as abstract methods are supposed to be.
You can't mix abstract and interface methods the way you're trying. If you were to declare 'Vector' abstract and override the implementation of A(), you'd be overriding 'Vector A()' from your abstract class, but that wouldn't implement the interface ISparseVector.Vector, which has a return type of ISparseVector.
Your use-case doesn't appear to require that 'Vector' be abstract.
I have need to use one of two custom file readers classes; one to read a fixed width file and one for a CSV file. Each of these readers will have certain properties, etc. I want to use factory methods and have private constructors so I can run some business logic before creating the objects.
EDIT: better examples
//simple class with it's own factory method
class Class1
{
private Class1()
{
//constructor code
}
public static Class1 CreateClass()
{
//do some business logic here
return new Class1();
}
}
What I want to be able to do is define a base class, then override the factory. I guess the problem is that a static class belongs to the base CLASS, so can never be overriden, even though they ARE inherited. This code works
public class BaseClass
{
//some common properties / fields here
public string SomeField;
//some common methods here
//empty constructor
protected BaseClass() { }
//cannot have a virtual static class!
//Would really like to make this a virtual method
public static BaseClass CreateClass()
{
throw new NotImplementedException("BaseClass is meant to be derived");
}
public static string DoCommonStaticThing(){
return "I don't know why you'd ever do this";
}
}
public class DerivedClass1 : BaseClass
{
//private constructor
private DerivedClass1() {}
//concrete factory method
//would really like to say "override" here
public static BaseClass CreateClass()
{
DerivedClass1 d1 = new DerivedClass1();
d1.SomeField = "I'm a derived class\r\n" + DoCommonStaticThing();
return d1;
}
}
EDIT: To clarify further, what I'm trying to do is put some common functionality in my base class, but define an interface for my file-format-specific methods. Some of the methods are common, but the business logic for the constructor(s) is file format specific. My code above works, but it seems to me it would be better to mark the base class factory method as virtual, and the derived class factory method as "override".
I tried to do this, but got "A static member cannot be marked as override, virtual, or abstract".
What's the right way to achieve my goals?
First, explaining your specific error message: you cannot inherit static members because they belong to the type being defined, not the instance of the type. Inheritance modifiers such as override, virtual, and abstract do not apply to static members.
Second:
Typically when you follow a factory pattern, you have a factory class whose job is to instantiate concrete classes and return those instances cast as a base class or interface. Details vary as to how the factory chooses which concrete class to instantiate, and I won't get into that, but at the fundamental level, that's what a factory does.
So in order to create a factory pattern using the example you provided, you'll need at least four types, which, following your example, could probably be named ReaderBase, ReaderFactory, CsvReader, and FixedWidthReader. Rather than ReaderBase, you might consider IReader -- the choice depends on whether your abstract class pre-implements any functionality that is shared across all Readers.
CsvReader and FixedWidthReader inherit from either IReader or ReaderBase, and ReaderFactory has at least one method called, for example, InstantiateReader, which returns an IReader or ReaderBase. InstantiateReader does the work of determining whether to instantiate a CsvReader or a FixedWidthReader, based on some external criteria.
In c# we can't create an obeject of a abstact class or interface it means abstract class do not have any constructor, is it true ?
or if it have then what is it's purpose there?
As others have said, abstract classes usually have constructors (either explicitly or the default one created by the compiler) - and any derived class constructor will have to chain through the abstract class's constructor in the normal way. That's the important bit... suppose you have an abstract class which stores the name associated with an instance - because you always want a name, and you don't want to write the Name property in each concrete derived class. You might provide a constructor which takes that name and assigns it to a field... and then every subclass constructor would have to go through that constructor, so that you still knew you'd always have a name. If you want to know more about constructor chaining, read my article on it.
Here's an example of that:
public abstract class DemoBase
{
private readonly string name;
public string Name { get { return name; } }
protected DemoBase(string name)
{
this.name = name;
}
// Abstract members here, probably
}
public class FixedNameDemo : DemoBase
{
public FixedNameDemo()
: base ("Always the same name")
{
}
// Other stuff here
}
public class VariableNameDemo : DemoBase
{
public VariableNameDemo(string name)
: base(name)
{
}
// Other stuff here
}
To further answer your comment on BoltClock's answer, asbtract classes can't have private abstract methods, but they can have private constructors. Indeed, it's sometimes useful to have only private constructors in an abstract class, because it means the class can only be derived from within the program text of the same class. This allows you to create pseudo-enums:
public abstract class ArithmeticOperator
{
public static readonly ArithmeticOperator Plus = new PlusOperator();
public static readonly ArithmeticOperator Minus = new MinusOperator();
public abstract int Apply(int x, int y);
private ArithmeticOperator() {}
private class PlusOperator : ArithmeticOperator
{
public override int Apply(int x, int y)
{
return x + y;
}
}
private class MinusOperator : ArithmeticOperator
{
public override int Apply(int x, int y)
{
return x - y;
}
}
}
In this respect, an abstract private method/property could make sense - it could be accessed by the base class but provided by the derived classes within the same class's program text. However, it's prohibited by the specification. Usually, protected abstract members would solve the same problem - but not quite always.
Good question. Here's why Abstract classes need constructors even though they cannot be instantited.
In any Object oriented language like C#, object construction is an hierarchical process. Look at the code below. When you instantiate any object of type DerivedClass, it must construct the base object first before creating the object of typeof DerivedClass. Here the base class may or may not be an Abstract class. But even when you instantiate an object of a concrete type derived from an abstract class it will still need to call the constructor of the Base class before the object of DerivedClass type is created, hence you always need a constructor for Abstract class. If you have not added any constructor, C# compiler will automatically add a public parameterless constructor to the class in the generated MSIL.
public class BaseClass
{
public BaseClass()
{
Console.WriteLine("BaseClass constructor called..");
}
}
public class DerivedClass : BaseClass
{
public DerivedClass()
{
Console.WriteLine("DerivedClass constructor called..");
}
}
DerivedClass obj = new DerivedClass();
//Output
//BaseClass constructor called..
//DerivedClass constructor called..
PS: Assuming, If Abstract base classes
are not allowed to have constructors
because they need not be instantiated,
the whole fundamentals of the object
oriented programming will go on toss.
The idea behind Abstract types are to
represent objects that have some
features and behaviours but not
complete as whole to allow independant
existence.
No. it means that operator new is not allowed to create object from this type of class.
The purpose might be that are allocated/initialized some properties of class.
abstract usually leave some methods to implement.
Regarding the interface, this structure holds only the signatures of method, delegates or events. That may be implemented in class that use interface. You cant create a object.
Read about new
EDIT:
What is the purpose of constructor in abstract class ?
When one class inherit another class, the parent class of it had to be created first while object is crated. In class do not implement some special constructor always is used default one [className()]. When you override some method then the implementation of functionality is taken form class which override the method. This is why method used in constructor should never be virtual. Same logic for abstract class, such class can have a lot of functionality, and only one method that should be implemented by child class.
Abstract classes have constructors but you can't call them directly as you can't directly instantiate abstract classes.
To answer your comment, the concept of a private abstract method or property makes no sense, because private prevents anybody else from accessing it, and abstract prevents itself from accessing it. So there would essentially be no possible way to call it.
EDIT: see Jon Skeet's answer on private constructors. Private members of other kinds cannot exist in abstract classes, though.
Abstract classes do have constructors. When you create an instance of a derived class, its parent class' constructors are called. This applies to classes derived from abstract classes as well.