I have a parent class
abstract class ClassPlugin
{
public ClassPlugin(eGuiType _guyType)
{
GuiType = _guyType;
}
public eGuiType GuiType;
public void Action() { }
}
I want all derived classes to implement the Action member and to define the guyType field.
To do that I have put it in the constructor, this is the only way that comes to mind.
Therefore an abstract class can be:
class ClassStartWF: ClassPlugin
{
public ClassStartWF(eGuiType _guyType)
{
GuiType = _guyType;
}
public void Action()
{
MessageBox.Show(GetType().Name);
}
}
the problem is that I get the error:
Severity Code Description Project File Line Suppression State
Error CS7036 There is no argument given that corresponds to the
required formal parameter '_guyType' of
'MainWindow.ClassPlugin.ClassPlugin(MainWindow.eGuiType)'
You should call the base class constructor in derived class constructor. Since you have create a constructor then compiler will not generate default constructor for your classes.
public ClassStartWF(eGuiType _guyType)
: base(_guyType)
{
// GuiType = _guyType; //this is not needed since the value is assigned in the base class constructor
}
Two problems...
First, you need to call the base class constructor from the derived type, as the base has no default constructor:
public ClassStartWF(eGuiType _guyType) : base(_guyType)
{
}
Since the base class takes care of setting the field you don't need to do it.
Secondly, you should make Action abstract in the base class and then override it in the derived class:
abstract class ClassPlugin
{
public abstract void Action();
}
class ClassStartWF: ClassPlugin
{
public ClassStartWF(eGuiType _guyType)
{
GuiType = _guyType;
}
public override void Action()
{
MessageBox.Show(GetType().Name);
}
}
At the moment you calls to Action won't dispatch to the derived instances when called through a base reference.
Also, rather than make GuiType a public variable you'd be better off making it a property:
public eGuiType GuiType{get; set;}
This will give you some control over the value. Also, you might want to consider making the setter private if it should only ever be set during construction.
Related
So I have a Vehicle class without a constructor. I want to make a new class called VehicleExtended which inherits from Vehicle.
The error is:
'Vehicle' does not contain a constructor that takes 0 arguments (CS1729)
Is it possible to inherit without having a constructor?
NOTE: I can't edit the base class because it's only it's metadata that I can see.
public class VehicleData : Vehicle
{
[BsonId]public int _id { get; private set;}
public bool IsCompany { get; private set;}
public int OwnerID { get; private set; }
public string modelName { get; private set;}
}
As we can see from the error message, base class Vehicle doesn't have constructors without arguments:
public class Vehicle {
...
// every Vehicle constructors want some parameters, e.g. id and ownerId
public Vehicle(int id, int ownerId) {...}
...
}
That's the compiler doesn't know how to create instance of VehicleData:
// Since VehicleData is inherited from Vehicle,
// Vehicle cosntructor should be executed.
// What arguments should be passed to it?
var test = new VehicleData();
You have to implement VehicleData constructor manually in which you should specify the arguments:
public class VehicleData : Vehicle
{
// When creating an instace, use -1 and -1 when calling base constructor
public VehicleData() : base(-1, -1) {}
...
}
Now the code above is legal:
// We don't want parameters when creating VehicleData instance
// When creating base class (Vehicle) -1 and -1 are used
var test = new VehicleData();
Edit: If base class (Vehicle) doesn't have any public or protected constructors (but private ones) you can't create base Vehicle instance from VehicleData and thus can't inherit from Vehicle. private constructors only is an old C++ trick; in case of C# in order to prevent from inheriting we should use sealed
It's possible, that the base class has a private constructor which can't be accessed. In this case you can't inherit the class.
Based on the error message I assume that the class VehicleData has an private zero argument constructor.
In this case you can not inherit from VehicleData.
e.g.
public class A
{
private A() {}
}
public class B : A
{
}
this will not compile.
But if there is an public or protected with a non-zeor argument list you can inherit from the class:
public class A
{
private A() {}
public A(int i) {}
}
public class B : A
{
public B() : base(0) {}
}
Also, if it turns out that Vehicle has only private constructores and you only want to add specificy behaivor and not any kinds of properties that are not computable from the ones that are already defined in Vehicle, instead of inheriting you could use extesnions-methodes.
public static VehicleExtesnion
{
public SomeType DoStuff(this Vehicle vehicle)
{
// do stuff with vehicle
}
}
I have a class with a method that accepts an argument which must be a Control with expected methods.
I've created an interface with those methods.
I've created an abstract class that inherits from Control and implements the interface putting all methods abstract (this is the type of my argument above).
Then i've created a class that inherits from TableLayoutPanel and implements the interface.
I create an instance of this class but then i cannot use it as the argument.
I know why. But what is the workaround? I know i could add a method to the interface that returns the Control instance. In this case, the TableLayoutPanel, but i wanted to use the instance itself...
Also, i don't want to make casts inside the method that receives the argument, it has to be "compile-time/type safe" to use in a library for example...
class CollapsibleList : Panel
{
public void AddItem(CollapsibleListItem item)
{
someContainer.Controls.Add(item);
item.CollapsibleListItemCollapse();
}
}
public interface ICollapsibleListItem
{
string CollapsibleListItemName { get; }
void CollapsibleListItemCollapse();
void CollapsibleListItemExpand();
}
public abstract class CollapsibleListItem : Control, ICollapsibleListItem
{
public abstract string CollapsibleListItemName { get; }
public abstract void CollapsibleListItemCollapse();
public abstract void CollapsibleListItemExpand();
}
class ListBoxCollapsibleListItem : TableLayoutPanel, ICollapsibleListItem
{
//... implemented interface methods
}
class Main
{
public void SomeMethod()
{
var item = new ListBoxCollapsibleListItem();
var collapsibleList = new CollapsibleList();
collapsibleList.AddItem(item as CollapsibleListItem); //cast error!
}
}
try below,
collapsibleList.AddItem(item as ICollapsibleListItem);
I have the following generic class:
internal class AutoRegisterThread<T> where T: AutoRegisterAbstract
{
field1....
method1...
}
I have 5 classes that implement AutoRegisterAbstract (abstract class).
and in my Main form (internal partial class MainForm : Form), I need to declare a field :
AutoRegisterThread<> _currentThread
without specifying the generic type, because I may initiate _currentThread as:
_currentThread=new AutoRegisterThread<implementedClass1>
or
_currentThread=new AutoRegisterThread<implementedClass2>
_currentThread: will be used across the Form (in many events)
Inherit from a non-generic base class:
internal abstract class AutoRegisterThreadBase { }
internal class AutoRegisterThread<T> : AutoRegisterThreadBase
where T: AutoRegisterAbstract
{
field1....
method1...
}
Your main form field can now be of type AutoRegisterThreadBase
Note, if desired, the non-generic parent class can have the same name as the generic class; in your case, AutoRegisterThread.
EDIT: Extended example, with usage:
internal abstract class AutoRegisterThreadBase { /* Leave empty, or put methods that don't depend on typeof(T) */ }
internal abstract class AutoRegisterAbstract { /* Can have whatever code you need */ }
internal class AutoRegisterThread<T> : AutoRegisterThreadBase
where T : AutoRegisterAbstract
{
private int someField;
public void SomeMethod() { }
}
internal class AutoRegisterWidget : AutoRegisterAbstract { /* An implementation of AutoRegisterAbstract; put any relevant code here */ }
// A type that stores an AutoRegisterThread<T> (as an AutoRegisterThreadBase)
class SomeType
{
public AutoRegisterThreadBase MyAutoRegisterThread { get; set; }
}
// Your code that uses/calls the above types
class Program
{
static void Main(string[] args)
{
var someType = new SomeType();
// Any sub-class of AutoRegisterThreadBase, including generic classes, is valid
someType.MyAutoRegisterThread = new AutoRegisterThread<AutoRegisterWidget>();
// You can then get a local reference to that type
// in the code that's created it - since you know the type here
var localRefToMyAutoRegisterThread = someType.MyAutoRegisterThread as AutoRegisterThread<AutoRegisterWidget>;
localRefToMyAutoRegisterThread.SomeMethod();
}
}
When you have a generic class in C#, you have to provide the type parameter. You could write another class that would not be generic. If there is any logic, that should be shared between generic and non-generic classes, you can move that logic to one more new class.
I have the following and at some point I need to create Failures for Validations. We suppose each type deriving from Validation has one and only one type deriving from Failure<T> where T is the aforementioned implementation of Validation.
As I have a growing number of implementations of Validation, I need to be able to instantiate the right type deriving from Failure<T>, and call the link method on it within a method that looks like
void recordFailureForValidation(Validation v) {
Type failureType = dict[v.GetType()];
Object failure = Activator.CreateInstance(failureType);
// how do I call failure.link(v) ?
}
At Runtime, a dictionary gives me the type deriving from Failure<T> given T.
I am able to instantiate Failure<T> (Failure1, Failure2, etc...), but I can't find how to call link on the public field reference of my newly created Failure instance (by making all uses that made sense to me of GetMethod, MakeGenericMethod, Invoke, etc...)
public class MyReferenceClass<T>
where T : Object, new() {
public void link(T arg) { ... }
}
public abstract class Failure<T>
where T : ValidationRule, new() {
...
public MyReferenceClass<T> reference;
...
}
public class Failure1 : Failure<Validation1> {
}
public class Failure2 : Failure<Validation2> {
}
public abstract class ValidationRule {
...
}
public class ValidationRule1 : ValidationRule {
...
}
public class ValidationRule2 : ValidationRule {
...
}
link is private since you do not specify a different accessibility. Make it public or internal:
public class MyReferenceClass<T>
where T : Object, new() {
public void link(T arg) { ... }
}
then you can call it from Failure<T> through the reference property:
public abstract class Failure<T>
where T : ValidationRule, new()
{
protected T Validation {get; set;};
public MyReferenceClass<T> reference;
}
public class Failure1 : Failure<Validation1>
{
public void Test()
{
this.reference.link(Validation);
}
}
Let Failures implement a non generic IFailure interface as well as a generic one in the same manner as IEnumerable and IEnumerable<T>
Create an abstract factory method within ValidationRule that has to be implemented by each concrete Validation
public ValidationRule1 : ValidationRule
{
public override IFailure ToFailure()
{
return new Failure1(this);
}
...
}
I have a baseclass which has public contructors.
The baseclass is not sealed and is not abstract.
There is one constructor which I desire to be sealed. Is this possible?
My current attempt results in syntax error saying the constructor cannot be sealed.
public sealed MyBase(string someParam)
Additional:
I wish to be able to instantiate the base class directly and have access to the sealed constructor. Derived classes cannot use that constructor via the derived constructors.
E.g.
public MyDerived() : base(string cant_access_my_sealed_constructor)
You can't do that. If the constructor is public, you can call it from constructors of derived classes. But you can do something close – you can have a private constructor and a public static method that calls it:
class MyBase
{
private MyBase(string someParam)
{
// some code
}
public static MyBase Create(string someParam)
{
return new MyBase(someParam);
}
protected MyBase() // or some other protected or public constructor
{ }
}
class MyDerived : MyBase
{
public MyDerived()
: base("foo") // won't compile, as requested
{ }
}
All constructors are "sealed" in that they cannot be "overridden." They can only be called from the constructor in a child class.
If you are hoping to prevent child classes from having a constructor with the same signature, that cannot be done.
Based on the additional information you added to the post, it sounds like what you want to do is make your constructor private, as Kyle suggested. This will prevent the child class from calling the constructor, but it won't prevent it from taking the same types of arguments:
public class Foo
{
private Foo(string s){
}
// Allowed
public Foo() : this("hello") {
}
}
public class Bar : Foo
{
// Allowed
public Bar(string s) : base(){
}
// Not allowed
public Bar(string s) : base(s){
}
}
If you want to prevent the constructor from being called by inherited classes, just mark it private.
Constructors aren't inherited by a child class, you have to explicitly call a base constructor if desired.
This code will call the base class' no-parameter constuctor when an instance of the child class is instantiated. Without it, the base class' constructor won't be called when creating a new instance of the child class.
public class A
{
public A()
{
}
}
public class B : A
{
public B()
: base()
{
}
}