I have a class Foo, which is a base class for a lot other classes such as Bar and Baz, and I want to do some calculation within Foo using the static members in Bar and Baz, as shown below:
public class Foo{
public result1 {
get{
return field1;
}
}
}
public class Bar : Foo{
public const int field1 = 5;
}
public class Baz : Foo{
public const int field1 = 10;
}
The only solution I can think of is wrap all the fields in a container, add an extra identifier for each object, and use a function to return the fields, like so
Bar : Foo{
public readonly int id = 0;
public static Wrapper wrapper;
}
public Wrapper GetWrapper(int id){
switch(id){
case 0:
return Bar.wrapper;
}
}
However, as you can see, I need to maintain one additional class and function, and I'd rather not to fragment my code. Is there any alternative?
Edit
What you are asking for, i.e. accessing a static or const value in a subclass from a base class is technically possible, but doing so will violate the principals of good SOLID OO design. Also, since you will need an instance of a specific subclass in order to be able to 'reason over' the type of the subclass in order to obtain the appropriate field1, there's little point approaching this problem statically.
Instead, the common, cleaner, approach here is to use subtype polymorphicism which will allow a calling method in the base class, or a method in an external class altogether, to access the appropriate value for 'field1' based on the subclass. This allows control over the value returned to remain inside the appropriate subclasses (i.e. as per your words, the code won't become "fragmented").
Alternative solution using subclass polymorphicism (recommended)
A subclass polymorphic approach (i.e. with the virtual/abstract and override keywords) will allow you to encapsulate the retrieval of a value (or object) which is customizable for each subclass. Here, the abstraction remains conceptually at "give me an integer value", and then the sub-class-specific implementations of 'how' to return the value can be abstracted (hidden) from the caller. Also, by marking the base property as abstract, you will force all subclasses to implement the property, so that the requirement to provide a value isn't forgotten about.
i.e. I would recommend a polymorphic approach like this:
public abstract class Foo
{
public abstract int Result { get; }
}
public class Bar : Foo
{
// This is implementation specific. Hide it.
private const int field1 = 5;
public override int Result
{
get { return field1; }
}
}
public class Baz : Foo
{
public override int Result
{
// No need for this implementation to be a constant ...
get { return TheResultOfAReallyComplexCalculationHere(); }
}
}
If there are no other reusable concrete methods on the base class Foo, then you could also model the abstraction as an interface, with the same effect:
public interface IFoo
{
int Result { get; }
}
Approaching this problem without polymorphicism (Not recommended)
Any compile-time attempt to access static fields on subclasses will typically require code somewhere to switch (or map) on the actually type of the subclass instance, e.g.:
public class Foo
{
public int result1
{
get
{
switch(this.GetType().Name)
{
case "Bar":
return Bar.field1;
case "Baz":
return Baz.field1;
default:
return 0;
}
}
}
public void MethodRequiringValueFromSubclass()
{
Console.WriteLine(result1);
}
}
public class Bar : Foo
{
public const int field1 = 5;
}
public class Baz : Foo
{
public const int field1 = 10;
}
The problem here is that the Open and Closed principal is violated, as each time a new sub class is added, the result1 method would need to be changed to accomodate the new class.
I'd suggest to use abstract function rather that using static member.
public abstract class Foo{
public result1 {
get{
return get_field1();
}
}
protected abstract int get_field1();
}
public class Bar : Foo{
public const int field1 = 5;
protected override int get_field1() { return field1;}
}
public class Baz : Foo{
public const int field1 = 10;
protected override int get_field1() { return field1;}
}
You either add constructor parameter to your Foo class which can be passed from inheritors, thus you don't need extra classes also you'll have less coupling
public class Foo
{
private readonly int _field1;
public Foo(int field1)
{
_field1 = field1;
}
}
or you can use it exactly from inheritors type as static/const members are members of class type
public class Foo
{
public result1
{
get
{
return Bar.field1;
}
}
}
but this gives your code less flexibility and more coupling.
Also you have an option by using virtual properties which you can implement in derrived classes and use in base:
public class Foo
{
public virtual int Field { get { return 0; } }
}
Instead of making Foo abstract as other answers suggested you can use virtual and override result1 in each child class
public class Foo
{
public virtual int result1 { get; }
}
public class Bar : Foo
{
public const int field1 = 5;
public override int result1
{
get { return field1; }
}
}
public class Baz : Foo
{
public const int field1 = 10;
public override int result1
{
get { return field1; }
}
}
If you want default result1 to return something else than 0 you can give it another value
public class Foo
{
public virtual int result1 { get; } = -1;
}
I always feel like a jerk when I answer my own question... Yet didn't see what I was expecting so I might as well just share what I've got after a night of mind boggling.
The reason I don't want to make the calculation abstract/virtual is because there are many subclasses and the formula is the same for all of them. I just refuse to type the same code 10-20 times repeatedly.
Couldn't make the static fields non static either, as they should be accessible at a class level plus they can get big, and they are the same for all instances.
The only solution I can come up that minimizes code fragment is something like this
public class Foo {
public class Wrapper {
Fields...
}
public Wrapper wrapper; // reference
public int result1 { get; }
}
public class Bar : Foo {
public static Wrapper subclassWrapper; // put in the implementation
public Bar() : base(){
wrapper = subclassWrapper;
}
}
So each instance now needs to hold an extra reference, however I don't need to keep a function. The wrapper is kept within the base class so it is less fragmented.
Related
Is there a way to modify the access of some attribute to a specific class? More specifically, I want to create a property that has a public get, but can only be set by a certain class.
Example:
public Class1
{
Class2.SomeInt = 5;
}
public static Class2
{
private static int someInt;
public static int SomeInt
{
get { return someInt; }
(give access to Class1 only somehow?) set { someInt = value; }
}
}
Update (more info):
I'm doing this in xna, I want the main type (Game1) to be the only thing that can modify a static helper class. It's for a group project in school, we're using SVN (not sure how that'd be relevant), I could just tell everyone in my group to avoid setting the values, but I was wondering if there was a better way.
This sounds like the friend access modifier, which C# doesn't have. The closest I've seen to this in C# is to have the "unrelated" class be an interface and have a private implementation within a class. Something like this:
public interface IWidget
{
void DoSomethingPublic();
}
public class SomeObject
{
private ObjectWidget _myWidget = new ObjectWidget();
public IWidget MyWidget
{
get { return _myWidget; }
}
private class ObjectWidget
{
public void DoSomethingPublic()
{
// implement the interface
}
public void DoSomethingPrivate()
{
// this method can only be called from within SomeObject
}
}
}
Code external to SomeObject can interact with MyWidget and sees anything that's on the IWidget interface, but code internal to SomeObject can also non-interface public members on MyWidget.
It seems to be impossible in C#. You can only use public, protected, protected internal, internal and private access modifiers.
But you can, for instance, make an assembly that contains only these two classes and set the internal modifier for the SomeInt setter or nest one class into another.
If you want to just hide a setter from the IntelliSense, you can define this setter in some interface and implement it explicitly:
public interface IHidden<T>
{
T HiddenPropery { set; }
}
public class SomeClass : IHidden<int>
{
private int someInt;
public int HiddenPropery
{
get { return someInt; }
}
int IHidden<int>.HiddenPropery
{
set { someInt = value; }
}
}
Usage:
// This works:
((IHidden<int>)new SomeClass()).HiddenPropery = 1;
// This doesn't:
new SomeClass().HiddenPropery = 1;
I'm trying to come up with a very neat way to alter an existing class. I'll try to explain what I came up with using this example;
abstract class AbstractX
{
public abstract string X();
protected internal abstract int Y();
}
// Execute all methods on another instance of AbstractX
// This is why the method(s) are 'protected *internal*'
class WrappedX : AbstractX
{
AbstractX _orig;
public WrappedX(AbstractX orig)
{
_orig = orig;
}
public override string X()
{
return _orig.X();
}
protected internal override int Y()
{
return _orig.Y();
}
}
// The AbstractX implementation I start with
class DefaultX : AbstractX
{
public override string X()
{
// do stuff
// call Y, note that this would never call Y in WrappedX
var y = Y();
return y.ToString();
}
protected internal override int Y()
{
return 1;
}
}
// The AbstractX implementation that should be able to alter *any* other AbstractX class
class AlteredX : WrappedX
{
public AlteredX(AbstractX orig)
:base(orig)
{
}
protected internal override int Y()
{
Console.WriteLine("Sweet, this can be added to any AbstractX instance!");
return base.Y();
}
}
Right, so the way I intend to use this is;
AbstractX x = new DefaultX();
x = new AlteredX(x);
Console.WriteLine(x.X()); // Should output 2 lines
Or to step away from the abstract example for a second and make it more concrete (should be self-explanatory);
FileWriterAbstract writer = new FileWriterDefault("path/to/file.ext");
writer = new FileWriterSplit(writer, "100MB");
writer = new FileWriterLogged(writer, "path/to/log.log");
writer.Write("Hello");
But (back to the abstract example) this isn't going to work. The moment AlteredX.X() is called (which isn't overridden) it goes to WrappedX.X(), which of course runs DefaultX.X() which uses it's own Y() method, and not the one I defined in AlteredX. It doesn't even know it exists.
I'm hoping it's obvious why I want this to work, but I'll explain further to make sure;
If I don't use WrappedX to created AlteredX, AlteredX will not be 'applyable' to any AbstractX instance,
thus making something like the FileWriter above impossible. Instead of;
FileWriterAbstract
FileWriterDefault : FileWriterAbstract
FileWriterWrap : FileWriterAbstract
FileWriterSplit : FileWriterWrap
FileWriterLogged : FileWriterWrap
It would become;
FileWriterAbstract
FileWriterDefault : FileWriterAbstract
FileWriterSplit : FileWriterDefault
// Implement Logged twice because we may want to use it with or without Split
FileWriterLogged : FileWriterDefault
FileWriterLoggedSplit : FileWriterSplit
And if I then created a new one, I'd have to implement it 4 times because I'd want it usable with;
Default
Split
Logged
Split+Logged
And so on...
So with that in mind, what's the best way to achieve this? The best I could come up with (untested) is;
class DefaultX : AbstractX
{
protected internal override Func<string> xf { get; set; }
protected internal override Func<int> yf { get; set; }
public DefaultX()
{
xf = XDefault;
yf = YDefault;
}
public override string X()
{
return xf();
}
protected override int Y()
{
return yf();
}
string XDefault()
{
var y = Y();
return y.ToString();
}
int YDefault()
{
return 1;
}
}
class AlteredX : WrappedX
{
Func<int> _yfOrig { get; set; }
public AlteredX()
{
// I'm assuming this class member doesn't get overwritten when I set
// base.yf in the line below.
_yfOrig = base.yf;
base.yf = YAltered;
}
private int YAltered()
{
Console.WriteLine("Sweet, this can be added to any AbstractX instance!");
return yfOrig();
}
}
Even if this does work, it seems really messy... does anyone have any suggestions?
One way to handle this would be to defer all of the internal operations to a separate, perhaps, internal utility class and provide a way for the wrapping classes to replace the implementation of the utility class. Note: this example requires any concrete, non-wrapping class to implement the utility class. A wrapper class may or may not choose to wrap the utility class. The key here is that the getter/setter for the utilities class in the base (abstract) class doesn't allow it to be overridden, thus every inheriting class uses the utility class as defined by it's constructor. If it chooses not to create it's own utilities, it defaults to that of the class it's wrapping - eventually making it all the way back to the concrete, non-wrapped composition root class if need be.
NOTE: this is very complex and I would avoid doing it. If possible use the standard decorator and only rely on public interface methods of the wrapped class. Also, the utility classes need not be inner classes. They could be injected via the constructor which might make it a bit cleaner. Then you would explicitly use the Decorator pattern on the utilities as well.
public interface IFoo
{
string X();
}
public abstract class AbstractFoo : IFoo
{
public abstract string X();
protected internal Footilities Utilities { get; set; }
protected internal abstract class Footilities
{
public abstract int Y();
}
}
public class DefaultFoo : AbstractFoo
{
public DefaultFoo()
{
Utilities = new DefaultFootilities();
}
public override string X()
{
var y = Utilities.Y();
return y.ToString();
}
protected internal class DefaultFootilities : Footilities
{
public override int Y()
{
return 1;
}
}
}
public abstract class AbstractWrappedFoo : AbstractFoo
{
protected readonly AbstractFoo Foo;
public AbstractWrappedFoo(AbstractFoo foo)
{
Foo = foo;
}
public override string X()
{
return Foo.X();
}
}
public class LoggedFoo : AbstractWrappedFoo
{
public LoggedFoo(AbstractFoo foo)
: base(foo)
{
Foo.Utilities = new LoggedUtilities(Foo.Utilities);
}
public override string X()
{
return Foo.X();
}
protected internal class LoggedUtilities : Footilities
{
private readonly Footilities _utilities;
public LoggedUtilities(Footilities utilities)
{
_utilities = utilities;
}
public override int Y()
{
Console.WriteLine("Sweet");
return _utilities.Y();
}
}
}
Now, this program
class Program
{
static void Main(string[] args)
{
AbstractFoo foo = new LoggedFoo(new DefaultFoo());
Console.WriteLine(foo.X());
}
}
Produces
Sweet!
1
I think you mixed up composition with inheritance.
When you call x.X() on an AlteredX object, the object calls X method of it's base object (WrappedX). The base object itself calls an object of type DefaultX which it has already wrapped. Now the Y method is called on an an object of DefaultX (_orig). You expect _orig knows there is something overriden in the caller of the caller! But how?
In this chain of call I don't see any point where overriding the method Y is involved.
I have a series of objects, lets call them buildings, that each share certain properties that are static for that building, but different for each building, such as price. I assumed that the best way to implement this was to create an abstract superclass with the shared price attribute and set the values in each subclass, but I cannot figure out how to get this to work. Here is an example of something I have tried:
using System;
public abstract class Buildings
{
internal static int price;
internal static int turnsToMake;
}
using System;
public class Walls : Buildings
{
public Walls()
{
price = 200;
turnsToMake = 5;
}
}
This works fine for construction, but if I want to check the price before creating it (to check if the player has enough money) then it just returns a null value. I'm sure that it is is a super simple fix, but I can't figure it out. Any help?
There is a "patchy" yet simple solution that's worth to consider. If you define your base class as a Generic class, and in deriving classes set T as the class itself, It will work.
This happens because .NET statically defines a new type for each new definition.
For example:
class Base<T>
{
public static int Counter { get; set; }
public Base()
{
}
}
class DerivedA : Base<DerivedA>
{
public DerivedA()
{
}
}
class DerivedB : Base<DerivedB>
{
public DerivedB()
{
}
}
class Program
{
static void Main(string[] args)
{
DerivedA.Counter = 4;
DerivedB.Counter = 7;
Console.WriteLine(DerivedA.Counter.ToString()); // Prints 4
Console.WriteLine(DerivedB.Counter.ToString()); // Prints 7
Console.ReadLine();
}
}
Don't use static. Static says that all instances of Building have the same value. A derived class will not inherit its own copy of the statics; but would always modify the base class statics. In your design there would only be one value for price and turnsToMake.
This should work for you:
public abstract class Buildings
{
internal int price;
internal int turnsToMake;
}
However, most people don't like using fields these days and prefer properties.
public abstract class Buildings
{
internal int Price { get; set; }
internal int TurnsToMake { get; set; }
}
I want to check the price before creating it […]
I suppose that's how you got to static fields; however, static and virtual behaviour cannot be combined. That is, you would have to re-declare your static fields for each subclass. Otherwise, all your subclasses share the exact same fields and overwrite each others' values.
Another solution would be to use the Lazy<T, TMetadata> type from the .NET (4 or higher) framework class library:
public class Cost
{
public int Price { get; set; }
public int TurnsToMake { get; set; }
}
var lazyBuildings = new Lazy<Buildings, Cost>(
valueFactory: () => new Walls(),
metadata: new Cost { Price = 200, TurnsToMake = 5 });
if (lazyBuildings.Metadata.Price < …)
{
var buildings = lazyBuildings.Value;
}
That is, the metadata (.Metadata) now resides outside of the actual types (Buildings, Walls) and can be used to decide whether you actually want to build an instance ( .Value) of it.
(Thanks to polymorphism, you can have a whole collection of such "lazy factories" and find a building type to instantiate based on the metadata of each factory.)
Building on Uri Abramson's answer above:
If you need to access the static property from within the Base class, use reflection to get the value from T. Also, you can enforce that Base must be inherited using T of the derived type.
e.g.
class Base<T> where T : Base <T> {
static int GetPropertyValueFromDerivedClass<PropertyType>(BindingFlags Flags = BindingFlags.Public | BindingFlags.Static, [CallerMemberName] string PropertyName = "")
{
return typeof(T).GetProperty(PropertyName, Flags)?.GetValue(null);
}
static int Counter{ get => GetPropertyValueFromDerivedClass(); }
}
static int DoubleCounter{ return Counter*2; } //returns 8 for DerivedA and 14 for DerivedB
}
If you have a better way to do this, please post.
Not as easy for the inheritor, but workable...
public abstract class BaseType
{
public abstract contentType Data { get; set; }
}
public class InheritedType : BaseType
{
protected static contentType _inheritedTypeContent;
public override contentType Data { get => _inheritedTypeContent; set => _inheritedTypeContent = value; }
}
I know that syntactically and conceptually the concepts of "virtual" and "static" members are diametrically opposed, but I'm trying to push the envelope a bit and see if there's a way to achieve the following:
Let's say I have an abstract class Animal, which has a property NumberOfLegs. My Cat class should have NumberOfLegs defined as 4, while Spider should have 8 legs. I would want to have code like this (obviously the code below will not compile):
public abstract class Animal {
public static abstract int NumberOfLegs { get; }
public void Walk() {
// do something based on NumberOfLegs
}
}
public class Cat : Animal {
public static override int NumberOfLegs { get { return 4; } }
}
public class Spider : Animal {
public static override int NumberOfLegs { get { return 8; } }
}
I want it to be static, because it's not dependent on instance; it's dependent only on the subclass type.
How would you do this?
I think the best compromise for you is to create a constant in each class for the number of legs. A constant is basically a static member which is readonly, which for this example makes sense, otherwise make it static.
Next, I would define an abstract Property for the Animal class and override it each subclass. This would allow inheritance and polymorphism to work, but each instance of the class would still reference the same value.
public abstract class Animal
{
public abstract int NumberOfLegs { get; }
public void Walk()
{
// do something based on NumberOfLegs
}
}
public class Cat : Animal
{
private const int NumLegs = 4;
public override int NumberOfLegs { get { return NumLegs; } }
}
public class Spider : Animal
{
private const int NumLegs = 8;
public override int NumberOfLegs { get { return NumLegs; } }
}
As far as not being to override static methods, I know it isn't what you want to hear but that's not possible. First of all, you use static members like Animal.Legs or Cat.Legs by specifying the class and not from an instance of the object. Therefore, if you define it as static, you won't even have access on it from an instance of the class, and there is no idea of polymorphism either (i.e. a function accepting a generic "Animal" cannot get how many legs it has and have it call the correct Property). If you are interested in how this works I suggest you read about Virtual Tables
In C# can a constant be overridden in a derived class? I have a group of classes that are all the same bar some constant values, so I'd like to create a base class that defines all the methods and then just set the relevant constants in the derived classes. Is this possible?
I'd rather not just pass in these values to each object's constructor as I would like the added type-safety of multiple classes (since it never makes sense for two objects with different constants to interact).
It's not a constant if you want to override it ;). Try a virtual read-only property (or protected setter).
Read-only property:
public class MyClass {
public virtual string MyConst { get { return "SOMETHING"; } }
}
...
public class MyDerived : MyClass {
public override string MyConst { get { return "SOMETHINGELSE"; } }
}
Protected setter:
public class MyClass {
public string MyConst { get; protected set; }
public MyClass() {
MyConst = "SOMETHING";
}
}
public class MyDerived : MyClass {
public MyDerived() {
MyConst = "SOMETHING ELSE";
}
}
Unfortunately constants cannot be overridden as they are not virtual members. Constant identifiers in your code are replaced with their literal values by the compiler at compile time.
I would suggest you try to use an abstract or virtual property for what you would like to do. Those are virtual and as such can (must, in the case of an abstract property) be overridden in the derived type.
Constants marked with const cannot be overridden as they are substituted by the compiler at compile time.
But regular static fields assigned to constant values can. I've had such a case just now:
class Columns
{
public static int MaxFactCell = 7;
}
class Columns2 : Columns
{
static Columns2()
{
MaxFactCell = 13;
}
}
If I just redefined the MaxFactCell field in the derived class instead, polymorphism wouldn't work: code using Columns2 as Columns would not see the overriding value.
If you need to restrict write (but not read) access to the field, using readonly would prohibit redefining it in Columns2. Make it a property instead, that's slightly more code:
class Columns
{
static Columns()
{
MaxFactCell = 7;
}
public static int MaxFactCell { get; protected set; }
}
class Columns2 : Columns
{
static Columns2()
{
MaxFactCell = 13;
}
}
Edit: This can have unexpected behaviour, see Shai Petel's remark below.
You can hide the inherited constant in a derived class by declaring the new constant new. I'm not sure this is a good practice, though.
class A
{
protected const int MyConst = 1;
}
class B : A
{
new private const int MyConst = 2;
}
to Work off dten + Tracker1's answer but updated for c# 6
public class MyClass {
public virtual string MyConst =>"SOMETHING";
}
...
public class MyDerived : MyClass {
public override string MyConst =>"SOMETHING ELSE";
}
You can force derived classes to have a value for a constant (well, a read-only property)
Make an interface containing a read-only property.
Put that interface on the base class.
Example:
public interface IHasConstant
{
string MyConst { get; }
}