I’m working with a state pattern and are wondering how to define variables so they can use in each child class. A protected variable in the abstract parent class may be the right choice, but with this, I’m wondering how to initialize these variables from the main class.
class Main
{
\\Initialize variable "file" here?
\\...
Context tc = new Context(new Step01());
\\...
}
class Context
{
private State ts;
// Constructor
public Context(State st)
{
this.State = st;
}
// Gets or sets the state
public State State
{
get
{
return st;
}
set
{
st = value;
}
}
public void Request()
{
ts.Handle(this);
}
}
abstract class State
{
protected string file = "file";
public abstract void Handle(Context tc);
}
class Step01 : State
{
tc.State = new Step02();
// use variable "file"
}
class Step02 : State
{
tc.State = new Step0x()
// use variable "file"
}
The example is a code snipped and don't work. I hope it helps to explain my question more accurate.
The quantity of child classes (Step0x) varies, so I think it's easier to define the variable only once in the parent class.
Does anybody have an idea how to initialize my variables in the main class?
Thank you.
Define file as constant:
abstract class State
{
protected const string file = "file";
public abstract void Handle();
}
Here is implementation of Step01 and Step02 which are using file:
class Step01 : State
{
public override void Handle(){}
public void PrintFile()
{
Console.WriteLine(string.Format("step1 + {0}", file));
}
}
class Step02 : State
{
public override void Handle(){}
public void PrintFile()
{
Console.WriteLine(string.Format("step2 + {0}", file));
}
}
And here is usage of the Step01 and Step02 classes:
static void Main(string[] args)
{
Step01 step1 = new Step01();
step1.PrintFile();
Step02 step2 = new Step02();
step2.PrintFile();
Console.ReadLine();
}
Related
I have a abstract base class, starting a timer which is common to all derived class,
public abstract class BaseClass
{
public virtual void Start() { _timer.Start(); }
}
Now I need to load different JSON configuration files for each derived class and create the file,
public class DerivedClass1 : BaseClass
{
private readonly List<config> configs = new List<config>();
public DerivedClass1()
{
configs = JsonSettings.GetConfigurations(#"./Configurations/1.json");
}
public override void Start()
{
base.Start();
foreach (var configuration in configs)
{
JsonSettings.CreateConfigFile(configuration);
}
}
}
public class DerivedClass2 : BaseClass
{
private readonly List<config> configs = new List<config>();
public DerivedClass2()
{
configs = JsonSettings.GetConfigurations(#"./Configurations/2.json");
}
public override void Start()
{
base.Start();
foreach (var configuration in configs)
{
JsonSettings.CreateConfigFile(configuration);
}
}
}
As I see there are lots of codes are duplicated in various derived class.
Can I move these piece of code as well as abstract base class or is there another way?
I think you could simplify your code to this:
public abstract class BaseClass
{
protected virtual List<config> configs { get; set; } = new List<config>();
public virtual void Start()
{
_timer.Start();
foreach (var configuration in configs)
{
JsonSettings.CreateConfigFile(configuration);
}
}
}
public class DerivedClass1 : BaseClass
{
public DerivedClass1()
{
configs = JsonSettings.GetConfigurations(#"./Configurations/1.json");
}
}
public class DerivedClass2 : BaseClass
{
public DerivedClass2()
{
configs = JsonSettings.GetConfigurations(#"./Configurations/2.json");
}
}
public interface BaseClass
{
void Start();
}
public interface IBaseClassUtil
{
void Start();
void setConfigs(List<config> configs);
}
public class BaseClassUtil : IBaseClassUtil
{
System.Timers.Timer _timer;
public List<config> _configs { get; set; } = new List<config>();
public void Start()
{
_timer.Start();
foreach (var configuration in _configs)
{
JsonSettings.CreateConfigFile(configuration);
}
}
public void setConfigs(List<config> configs)
{
_configs = configs;
}
}
public class DerivedClass1 : BaseClass
{
private IBaseClassUtil _baseUtility;
public DerivedClass1(IBaseClassUtil baseUtility)
{
_baseUtility = baseUtility;
_baseUtility.setConfigs( JsonSettings.GetConfigurations(#"./Configurations/1.json"));
}
public void Start()
{
_baseUtility.Start();
}
}
public class DerivedClass2 : BaseClass
{
private IBaseClassUtil _baseUtility;
public DerivedClass2(IBaseClassUtil baseUtility)
{
_baseUtility = baseUtility;
_baseUtility.setConfigs(JsonSettings.GetConfigurations(#"./Configurations/2.json"));
}
public void Start()
{
_baseUtility.Start();
}
}
This might be oveer engineered. Or might not suit ur current requirement.
Advantages would be
In future if you want u want to have different implementation for IBaseClassUtil it will be easier
And huge advantage would be this code is testable
If the classes differ by nothing but the configuration path, then you can have only one derived class that takes the path as a parameter in its ctor.
public DerivedClass(string configurationPath)
{
configs = JsonSettings.GetConfigurations(configurationPath);
}
Put please note that a decision on including inheritance in your architecture is not about code duplication, and by not giving us any information on the functions or even names of the classes (BaseClass and DerivedClass mean nothing. What do they represent? What's their function? Why are they related?) you give us no way of really helping you with your design.
I have a class with a PictureBox created as followed:
public class Tile
{
public PictureBox tilePB = new PictureBox(); //properties don't matter in this case
}
I also have a class GameManager. This is like a referee.
I want to make it so the BackColor of Tile.tilePB can only be edited by Gamemanager and nothing else, and no other class.
I currently have a public PictureBox for Gamemanager (to edit) and a public get function for other classes, but I want to actually make this a valid system instead of what I have right now.
Is this even possible? Please include explenation for the required code.
EDIT: I ran into an issue that I hadn't thought off: class Gamemanager is a static class. I do everything in that class via public static functions. Is this still possible? Since this doesn't work.
You can't do this at compile time, but it can be done at runtime:
public class PictureBox
{
private Color _backColor;
public void SetBackColor(Color color)
{
//getting class type that called this method
var stackTrace = new StackTrace();
var stackFrames = stackTrace.GetFrames();
var callingFrame = stackFrames[1];
var method = callingFrame.GetMethod();
//checking if the class type is GameManager
if (!method.DeclaringType.IsAssignableFrom(typeof(GameManager)))
{
throw new FieldAccessException("Only GameManager can set the background color of a PictureBox!");
}
_backColor = color;
}
public Color BackColor => _backColor;
}
public class Tile
{
public PictureBox tilePB { get; set; }
}
//example GameManager class
public class GameManager
{
public void SetBackground()
{
var someTile = new Tile()
{
tilePB = new PictureBox()
};
var someColor = new Color();
someTile.tilePB.SetBackColor(someColor);
}
}
//example class that may want to set picturebox background color
public class MaliciousClass
{
public void SetBackground()
{
var someTile = new Tile()
{
tilePB = new PictureBox()
};
var someColor = new Color();
someTile.tilePB.SetBackColor(someColor);
}
}
Then somewhere:
var gm = new GameManager();
var mc = new MaliciousClass();
gm.SetBackground(); //this is fine
mc.SetBackground(); //this will throw an exception
If you don't want to throw an exception or you want to do something different when "not authorized" class is trying to access the SetBackColor method then just replace throw new FieldAccessException() with return or whatever you want.
Bare in mind the approach presented here is inefficent and it just presents that in can be done at runtime and nothing more than that.
Not sure if this is exactly what you are looking for, but I made this quick test and it seems to be able to differentiate the calling class:
class Program
{
static void Main(string[] args)
{
Type1 something1 = new Type1();
Type2 something2 = new Type2();
something1.runTest();
something2.runTest();
Console.ReadKey();
}
public class Type1
{
public void runTest()
{
Testing.edit(this);
}
}
public class Type2
{
public void runTest()
{
Testing.edit(this);
}
}
public static class Testing
{
public static void edit(object obj)
{
// This is where you test the calling class to make sure
// it is allowed to edit.
Console.WriteLine(obj.GetType().ToString());
}
}
}
The only way I can think of where you enforce this at compile time, end up being a bit complicated. I don't think you'll want to do this.
You can create an interface with properties/methods for everything that only the GameManager is allowed to do. You can implement this interface in a private inner class below Tile, and make sure the only way this object is created is by passing in a GameManager that receives it. Now, the only way the access can 'leak' is if the GameManager 'gives away' the object.
public class GameManager {
public void AddTile(Tile t, Tile.IManagerHook m) {
m.SomeProperty = "set from manager";
}
}
public class Tile
{
public object SomeProperty { get; private set; }
public Tile(GameManager manager) {
manager.AddTile(this, new ManagerHook(this));
}
public interface IManagerHook {
object SomeProperty {get; set;}
}
private class ManagerHook : IManagerHook {
private Tile _tile;
public ManagerHook(Tile t) {
_tile = t;
}
public object SomeProperty {
get{ return _tile.SomeProperty;}
set { _tile.SomeProperty = value; }
}
}
}
(seems) Simply not possible
After asking several programmers, the way I have coded everything and what I want seems to be simply impossible without immensely complicated code - to the point you are better off refacturing everything. Since class Gamemanager is a static class, there will be no instances of it so you can not check if the 'object' that called it is of class Gamemanager. this also doesn't work since Gamemanager is, agian, static.
I know that what i need help with is not called the Parent but that was the closest word i could think of to describe this situation.
This is not actual code i'm using.
I have MainClass which contains object ObjectA.
class MainClass
{
public int mode = 0;
ObjectA obj = new ObjectA();
}
I need to access the mode variable from the ObjectA object. Is this possible? I feel like if i could at least call a method in MainClass from obj i would be all set. Also I'm aware calling MainClass a parent in this sense is incorrect, what is the correct term for both the MainClass and obj in this.
Assuming you are able to change MainClass, I can think of two options:
Add a reference to MainClass when you create an ObjectA instance.
Like you said in your comments, use events.
Using a reference:
class MainClass
{
public int mode = 31416;
ObjectA obj;
public MainClass()
{
obj = new ObjectA(this);
}
public int GetMainClassMode()
{
return mode;
}
public void Test() {
Console.WriteLine("Calling test method inside obj");
obj.Test();
}
}
class ObjectA {
MainClass parent = null;
public ObjectA(MainClass parent)
{
this.parent = parent;
}
public void Test()
{
if (parent != null)
{
Console.WriteLine("Getting mode from 'parent' MainClass");
Console.WriteLine(string.Format("Mode = {0}", parent.GetMainClassMode()));
}
}
}
Using events:
class MainClass
{
public int mode = 31416;
ObjectA obj = new ObjectA();
public MainClass()
{
obj.ValueReturnEvent += HandleValueReturnEvent;
}
public int GetMainClassMode()
{
return mode;
}
// Handle event, return data
private int HandleValueReturnEvent(object sender, EventArgs e)
{
return mode;
}
public void Test() {
Console.WriteLine("Calling test method inside obj");
obj.Test();
}
}
class ObjectA {
// delegate
public delegate int ReturnValueEventHandler(object sender, EventArgs args);
// event
public event ReturnValueEventHandler ValueReturnEvent;
public void Test()
{
// make sure at least one subscriber
if (ValueReturnEvent != null)
{
// note the event is returning a value
var myValue = ValueReturnEvent(this, null);
Console.WriteLine("Getting mode from 'parent' MainClass");
Console.WriteLine(string.Format("Mode = {0}", myValue));
}
}
}
On both cases, you get this output:
Calling test method inside obj
Getting mode from 'parent' MainClass
Mode = 31416
Even though you've got your answer, you could also simply inject it into your ObjectA ... have a constructor that takes an int, and when you create the object pass the mode in and save it in that object.
I find it cleaner that the object uses whatever it needs from its scope, rather than accessing the parent to ask for a variable.
I'm not saying it might not be needed, it just another thought.
You'll have to wire things up to let the child know about the parent for this to work. Something like this:
class ParentClass
{
public int mode = 0;
public ChildClass child = null;
public ParentClass()
{
child = new ChildClass(this);
}
}
class ChildClass
{
public readonly ParentClass parent = null;
public ChildClass (ParentClass parent)
{
this.parent = parent;
}
public int MethodThatReadsParentMode()
{
int mode = parent.mode;
return mode;
}
}
You make field mode public, so I assume it's possible that someone who uses class MainClass do can change this field.
Let's assume program looks like this.
class Program {
var main = new MainClass();
main.mode = 1;
}
Your obj field is private, so Program cannot access it.
So, when someone changed field mode, ObjectA should get new value of field mode.
Possible solution:
class ObjectA {
public int Mode { get; set; }
}
class MainClass {
private obj = new ObjectA();
public int Mode {
get { return this.obj.Mode; }
set { this.obj.Mode = value; }
}
}
There is another option in case field mode belongs to MainCalss.
class ObjectA {
private int mode;
public ObjectA(int mode) {
this.mode = mode;
}
// you can create property instead of method
// I'm not sure how you use this variable, so I just added set method
public void SetMode(int mode) {
this.mode = mode;
}
}
class MainClass {
private int mode = 0;
private obj = new ObjectA();
public int Mode {
get { return this.mode; }
set {
this.obj.SetMode(value);
this.mode = value;
}
}
}
I have the following class :
public class MyFragment
{
/// members + methods
void proc();
}
public class MyProc
{
/// members + methods
}
public class MyClass
{
private MyProc m_proc;
private MyFragment m_frag;
public MyClass(MyFragment fr)
{
m_proc = new MyProc();
m_frag = new MyFrag();
m_frag.proc();
}
}
For the method void proc() of class MyFragment I can not change not signature ,nor return type. But can change the implementation
My goal is to update m_proc of MyClass with some data generated inside MyFragment::proc()
I thought about :
Generate inside MyFragment ,the object from MyProc class, populate it in the MyFragment::proc()
and after that copy it to MyClass.m_proc.
On the other hand I don`t like to much the idea of copying...how can it be done more effectively
You can write another method, which accepts MyProc as argument, and call this method from proc:
public class MyFragment
{
/// members + methods
public void proc()
{
// just pass dummy argument
ProcEx(new MyProc());
}
public void ProcEx(MyProc myProc)
{
// fill myProc
}
}
public class MyClass
{
private MyProc m_proc;
private MyFragment m_frag;
public MyClass(MyFragment fr)
{
m_proc = new MyProc();
m_frag = new MyFrag();
m_frag.ProcEx(m_proc);
}
}
P.S. CPP-styled member names drives me crazy.
I think I couldnt do this thing, but I try to ask (maybe :)).
Suppose I have this Main class :
public class UiUtils
{
public static MyObject myObject;
public UiUtils()
{
myObject=new MyObject();
}
}
now if I want to try to call this instance from another Context Class (web application), I do this :
public partial class context_eventi_CustomClass : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
Console.Write(UiUtils.myObject.Title());
}
}
but what I'd like to do is this :
public partial class context_eventi_CustomClass : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
Console.Write(myObject.Title());
}
}
so, use directly myObject and not UiUtils.myObject :)
I think this is not possible, but maybe I wrong and there are any strategies :) Thanks
** EDIT **
my solution for the moment :
public class UiUtils
{
public static MyObject myObject;
public UiUtils()
{
myObject=new MyObject();
iContext.myObject = myObject;
}
}
public class iContext : System.Web.UI.UserControl
{
public static MyObject myObject;
public iContext()
{
}
public iContext(MyObject myObject)
{
myObject = myObject;
}
}
public partial class context_eventi_CustomClass : iContext
{
protected void Page_Load(object sender, EventArgs e)
{
Console.Write(myObject.Title());
}
}
seems to works! What do you think about?
Per MSDN,
A static method, field, property, or
event is callable on a class even when
no instance of the class has been
created. If any instances of the class
are created, they cannot be used to
access the static member. Only one
copy of static fields and events
exists, and static methods and
properties can only access static
fields and static events. Static
members are often used to represent
data or calculations that do not
change in response to object state.
and
"To access a static class member, use the name of the class instead of a variable name to specify the location of the member."
and
The static member is always accessed
by the class name, not the
instance name
#Daniel Earwicker says in his answer on SO here:
...Static members fail to integrate
well with inheritance. It makes no
sense to have them heritable. So I
keep static things in separate static
classes...
So I am not clear on your design why MyObject needs to be static. All you are trying to save is a little typing, but inheritance will not help you here either.
Edit:
I tried to replicate your code in a simple console application. The output is not what you would expect:
namespace ConsoleApplication1
{
public class UiUtils
{
public static int myObject = 1;
public UiUtils()
{
myObject = new int();
iContext.myObject = myObject;
Console.WriteLine("This is UiUtils\n");
}
}
public class iContext
{
public static int myObject = 2;
public iContext()
{
Console.WriteLine("This is iContext\n");
}
public iContext(int myObject)
{
myObject = myObject;
}
}
public class iContext2 : iContext
{
public static int myObject = 3;
public iContext2()
{
Console.WriteLine(myObject.ToString() + "\nThis is iContext2\n");
Console.WriteLine(iContext.myObject.ToString());
}
}
class Program
{
static void Main(string[] args)
{
iContext2 icontext = new iContext2();
Console.In.ReadLine();
}
}
}
The output ends up being this:
This is iContext
3
This is iContext2
If you add a call to iContext.myObject, then it outputs it's number:
This is iContext
3
This is iContext2
2
To access the object without typing the class you can use inheritance.
public class CustomClass : UiUtils
This will share UiUtils properties with CustomClass