I'm deriving a class from a parameterless-constructor class like this:
public class Base
{
public Base(Panel panel1)
{
}
}
public class Derived : Base
{
public Derived() : base(new Panel())
{
//How do I use panel1 here?
}
}
How can I refer to panel1 in Derived?
(Simple workarounds welcome.)
Adil's answer assumes that you can modify Base. If you can't, you can do this:
public class Derived : Base
{
private Panel _panel;
public Derived() : this(new Panel()) {}
private Derived(Panel panel1) : base(panel1)
{
_panel = panel1;
}
}
You need to define Panel in Base, you can use protected instead of public as well. Read more aboud access speicifiers here
public class Base
{
public Panel panel {get; set;};
public Base(Panel panel1)
{
panel = panel1;
}
}
public class Derived : Base
{
public Derived() : base(new Panel())
{
// this.panel
}
}
public class Base
{
// Protected to ensure that only the derived class can access the _panel attribute
protected Panel _panel;
public Base(Panel panel1)
{
_panel = panel1;
}
}
public class Derived : Base
{
public Derived() : base(new Panel())
{
// refer this way: base.panel
}
}
Further if you want to provide only a get and not a set for the derived classes you can do this:
public class Base
{
// Protected to ensure that only the derived class can access the _panel attribute
private Panel _panel;
public Base(Panel panel1)
{
_panel = panel1;
}
protected Panel Panel
{ get { return _panel; } }
}
public class Derived : Base
{
public Derived() : base(new Panel())
{
// refer this way: base.Panel (can only get)
}
}
Two ways:
public class Derived : Base
{
Panel aPanel;
public Derived() : this(new Panel()) {}
public Derived(Panel panel) : base(aPanel)
{
//Use aPanel Here.
}
}
OR
public class Base
{
protected Panel aPanel;
public Base(Panel panel1)
{
aPanel = panel1
}
}
Related
I've been studying how to use inherited classes in C#. I have no clue whatsoever as to why my code in invalid.
What I'm trying to achieve is to have one class (Child) that inherits from another (Parent). Each class should have its own constructor. The error reads:
<< CS7036 There is no argument given that corresponds to the required
<< formal parameter 'isOpen' of 'Parent.Parent(bool)'
public class Parent
{
internal bool IsOpen;
public Parent(bool isOpen)
{
this.IsOpen = isOpen;
}
}
public class Child : Parent
{
public Child(bool isOpen)
{
this.IsOpen = isOpen;
}
}
You need to pass it down to the parent via the base keyword:
public class Parent
{
internal bool IsOpen;
public Parent(bool isOpen)
{
this.IsOpen = isOpen;
}
}
public class Child : Parent
{
public Child(bool isOpen)
: base(isOpen)
{
}
}
You need to call the constructor of the base class (Parent) in your subclass:
public class Parent
{
internal bool IsOpen;
public Parent(bool isOpen)
{
this.IsOpen = isOpen;
}
}
public class Child : Parent
{
public Child(bool isOpen) : base(isOpen)
{
}
}
This also removes the need for you to set IsOpen again in the constructor of Child.
I'm working on a project that has a variety of classes that derive from class View, where View provides some common methods and where the derived classes have fields that reference UI elements specific to that view. For example (in C#):
public abstract class View
{
public virtual void Initialize(){}
public virtual void Activate(){}
public virtual void Deactivate(){}
}
public class MainScreenView : View
{
private ImageView portraitImageView;
private ImageView landscapeImageView;
public MainScreenView(ImageView portrait, ImageView landscape)
{
portraitImageView = portrait;
landscapeImageView = landscape;
}
public override Initialize()
{
base.Initialize();
portraitImageView.Initialize(); // I would like to eliminate these calls!
landscapeImageView.Initialize();
}
public ImageView GetPortrait() { return portraitImageView; }
public ImageView GetLandscape() { return landscapeImageView; }
}
public class ImageView : View
{
private Image image;
public ImageView(Image image) { this.image = image; }
public override void Initialize() { base.Initialize(); image.Show(); }
public Image GetImage() { return image; }
}
In this example I have to call Initialize() on all the ImageViews when MainScreenView.Initialize is called. This feels error prone and inconvenient, because an Initialize() call has to be added every time a new sub-view is added to the MainScreenView composition. Therefore, I would like to eliminate the need for these calls in the derived classes, but I want to maintain the fields to the view-specific fields.
My idea is to add a collection of Views to the base class, which can then recursively be Initialized(), as follows:
public abstract class View
{
private List<View> subViews;
public virtual void Initialize()
{
foreach(View in subViews) { view.Initialize(); }
}
// This gets called before Initialize() is called.
public void AddSubViews(View[] views)
{
subViews = new List<View>();
subViews.AddRange(views);
}
}
public class MainScreenView : View
{
private ImageView portraitImageView;
private ImageView landscapeImageView;
public MainScreenView()
{
portraitImageView = ???;
landscapeImageView = ???;
}
// Even if View.subViews had been protected instead of private, this couldn't return an element from the list because the required index is unknown.
public ImageView GetPortrait() { return portraitImageView; }
public ImageView GetLandscape() { return landscapeImageView; }
}
public class ImageView : View
{
private Image image;
public ImageView() { this.image = ??? }
public override void Initialize() { base.Initialize(); image.Show(); }
public Image GetImage() { return image; } // Even if View.subViews had been protected instead of private, this couldn't return an element from the list because the required index is unknown.
}
However, because all the individual sub-views are now 'anonymous' (they are accessed by index instead of a field name), this won't work for me, unless I also add the sub-views through the derived class' constructor as I did in my first example, where I can't enforce that the objects passed to the contructor are the same objects that are in the list, or call AddSubViews from the derived class' constructor where the sub-views are manually added every time a new sub-view is added... which has the same issue as calling Initialize() on sub-views in the derived classes.
So my question is: is there a way to have all Initialization calls of sub-views being done in the View base class, while still being able to provide derived-class-specific elements without passing references to those elements to the derived class' constructor?
UPDATE: If you want to be sure all sub views are initialized (i.e. nobody forget to add them to base class list of sub views) you can use reflection approach. Here is main idea:
public interface IView // you don't need abstract class
{
void Initialize();
}
Use reflection to get all class fields which implement IView and was initialized:
public class View : IView
{
private IView portraitView;
private IView landscapeView;
// assign some values to sub-views
public virtual void Initialize()
{
var flags = BindingFlags.NonPublic | BindingFlags.Instance;
var subViews = from field in GetType().GetFields(flags)
let value = field.GetValue(this)
where value != null && value is IView
select (IView)value;
foreach (var subView in subViews)
subView.Initialize();
}
}
Simple as that. Now if anyone will add field of IView type to your class it will be initialized with other sub-views.
ORIGINAL ANSWER: Just add both views to base class subViews list:
public MainScreenView(ImageView portrait, ImageView landscape)
{
portraitImageView = portrait;
landscapeImageView = landscape;
AddSubViews(new View [] { portrait, landscape });
}
Also keep in mind that you are re-creating subViews list each time when you are trying to add new views:
public void AddSubViews(View[] views)
{
subViews = new List<View>(); // here
subViews.AddRange(views);
}
I believe it's better to create subViews list only once during class field initialization:
private readonly List<View> subViews = new List<View>();
public void AddSubViews(params View[] views) // you can use params here
{
subViews.AddRange(views);
}
Now you simply can call
AddSubViews(portrait, landscape);
You can use the following pattern:
public abstract class View
{
private IEnumerable<View> SubViews { get; }
protected View(params View[] subViews)
{
SubViews = subViews;
}
public void Initialize()
{
OnInitialize();
foreach (var view in SubViews)
{
view.Initialize();
}
}
protected abstract void OnInitialize();
}
Now you concrete views will look like:
public class MainScreenView : View
{
private readonly ImageView portraitImageView;
private readonly ImageView landscapeImageView;
public MainScreenView(ImageView portrait, ImageView landscape)
: base(portrait, landscape)
{
portraitImageView = portrait;
landscapeImageView = landscape;
}
protected override void OnInitialize() { }
public ImageView GetPortrait() { return portraitImageView; }
public ImageView GetLandscape() { return landscapeImageView; }
}
public class ImageView : View
{
private readonly Image image;
public ImageView(Image image)
: base()
{
this.image = image;
}
protected override void OnInitialize() { image.Show(); }
public string GetImage() { return image; }
}
And finally,
var main = new MainScreenView(new ImageView(portraitImage), new ImageView(landScapeImage));
main.Initialize();
will initialize correctly all views.
If I have this hierarchy of classes:
Class Shape
{
public bool closedPath;
}
class Circle : Shape
{
}
class Line: Shape
{
}
Here I know that all circles are closed paths.
How to set the value of closedPath field to these defaults without the need to assign its value when instantiating an object of that said class?
You can declare your closedPath as a virtual read-only property and then define it in descendant classes:
class Shape
{
public virtual bool closedPath {get;}
}
class Circle : Shape
{
public override bool closedPath => true;
}
class Line: Shape
{
public override bool closedPath => false;
}
Things you might also consider are:
changing your Shape class to the abstract class or to the IShape interface.
You can also achieve the same result with a read-only field and initialize that field in the constructor.
You can pass a value to the base constructor:
class Shape
{
public bool closedPath;
public Shape(bool closedPath)
{
this.closedPath = closedPath;
}
}
class Circle : Shape
{
public Circle()
: base(true)
{
}
}
class Line : Shape
{
public Line()
: base(false)
{
}
}
Then you'd get:
void SomeMethod()
{
Shape circle = new Circle();
Console.WriteLine(circle.closedPath); // True
Shape line = new Line();
Console.WriteLine(line.closedPath); // False
}
I have a very simple controls library for Windows Forms and I am getting problems to implement accessibility.
I have a very simple Form with a member that contains a list of controls of my library, and I have overriden the CreateAccessibilityInstance:
public partial class Form1 : Form
{
protected override AccessibleObject CreateAccessibilityInstance()
{
return new AccessibleForm(this);
}
public MyContainer MyContainer;
public Form1()
{
InitializeComponent();
MyContainer = new MyContainer();
MyContainer.Controls.Add(new MyButton());
}
}
The AccessibleForm class looks like:
public class AccessibleForm: Control.ControlAccessibleObject
{
private Form1 form1;
public AccessibleForm(Form1 owner):base(owner)
{
this.form1 = owner;
}
public override AccessibleObject GetChild(int index)
{
return this.form1.MyContainer.Controls[index].AccessibilityObject;
}
public override int GetChildCount()
{
return this.form1.MyContainer.Controls.Count() ;
}
}
MyContanier and MyButton classes inherits from BaseControl, they are very easy:
public class BaseControl : Control
{
protected override AccessibleObject CreateAccessibilityInstance()
{
return new AccessibleObject();
}
}
public class MyContainer:BaseControl
{
public List<BaseControl> Controls { get; set; }
public MyContainer()
{
this.Controls = new List<BaseControl>();
}
}
public class MyButton:BaseControl
{
}
The point is that when I run the UIVerify tool to see if my controls are generating the correct structure I can not see them:
Another point is, that if I modify the GetChild method from AccessibleForm class in this way:
public override AccessibleObject GetChild(int index)
{
return new AccessibleObject();
////return this.form1.MyContainer.Controls[index].AccessibilityObject;
}
I can see a node on the UIVerify:
But modifying the GetChild method to return a custom accessible object it shows me nothing.
Why are not my controls on the tree?
I do not know what I am missing.
Override Name,value,Role in AccessibleForm class
public interface IMyControl<in T> where T : ICoreEntity
{
void SetEntity(T dataObject);
}
public class MyControl : UserControl, IMyControl<DataObject> // DataObject implements ICoreEntity
{
void SetEntity(T dataObject);
}
All fine so far, but why does this create null?
var control = LoadControl("~/Controls/MyControl.ascx"); // assume this line works
IMyControl<ICoreEntity> myControl = control;
myControl is now null...
You cannot have dataObject as parameter for this to work. Methods could only return it.
public interface ICoreEntity { }
public class DataObject: ICoreEntity { }
public interface IMyControl<out T> where T : ICoreEntity
{
T GetEntity();
}
public class MyControl : IMyControl<DataObject> // DataObject implements ICoreEntity
{
public DataObject GetEntity()
{
throw new NotImplementedException();
}
}
Now you can:
MyControl control = new MyControl();
IMyControl<ICoreEntity> myControl = control;