C#, read / write separation and properties. Pattern required - c#

Ok, so C# has properties
public int Prop {get;set;}
I can put the getter and the setter on separate interfaces like this:
public interface IRead
{ int AnInt { get; } }
public interface IWrite
{ int AnInt { set; } }
And then mix and match them like so:
public class WorkingClass : IRead, IWrite
{
public int AnInt { get; set; }
}
Where it starts to go wrong is where I might have a base object.
public class BaseClass : IRead
{
private int _anInt;
public BaseClass(int anInt)
{ _anInt = anInt; }
public virtual int AnInt
{ get { return _anInt; } }
}
I then want a derived class which can write as well.
public class Derived : BaseClass, IWrite //bits elided
{
public override int AnInt
{
get { return base.AnInt; }
set { throw new NotImplementedException(); } //<-- error
}
}
Which of course doesn't work.
This actually doesn't come up that often. I prefer to have methods with change state and have properties read only. This is design 101 I guess, but as a contrived example, I'd have an Age property with just a get and then a method called IncreaseAge.
So with that all in mind. If you did want to have a mutable object with seperate read and write interfaces how would you do it?
I could do it in a Java-esque way with separate getter/setter methods on each interface. But that negates the benefits of properties + one of the cop programs will yell at me.

You can have the base setter protected and have the derived class implement IWrite explicitly delegating to the base setter:
public class BaseClass : IRead {
public BaseClass(int anInt) { AnInt = anInt; }
public int AnInt {
get; protected set;
}
}
public class Derived : BaseClass, IWrite {
public Derived(int anInt) : base(anInt) { }
int IWrite.AnInt {
set { base.AnInt = value; }
}
}
(The keyword base can even be omitted and the base property doesn't need to be virtual.)

Related

What is an appropriate way to change property accessors on sub classes whilst maintaining polymorphism?

I have a few classes that inherit from a base class for which I wish to change the implementation of a property and method. I also require the base class and all sub classes to be be polymorphic, so I can later create a collection of any type that implements a particular interface.
When i create instances of my classes that implement an interface, I want to use properties and methods on that class (implemented by the interface), not the base class.
This is my simplified implementation of the issue that provides the desired output but does have a code smell...
class Program
{
static void Main(string[] args)
{
IGrid one = new TextField();
IGrid two = new SelectList();
one.Click();
two.Click();
Console.WriteLine(one.Text);
Console.WriteLine(two.Text);
Console.ReadLine();
}
}
public interface IGrid {
string Text { get; set; }
void Click();
}
public class Control : IGrid {
public string Text {
get { return "Hello Control!"; }
set { }
}
public virtual void Click() {
Console.WriteLine("In the Control!");
}
}
public class SelectList : Control, IGrid {
public int Number { get; set; }
public new string Text {
get {
return "Hello Select!";
}
set { Number = int.Parse(value); }
}
public override void Click() {
Console.WriteLine("In the Select!");
}
}
public class TextField : Control, IGrid {
public int Number { get; set; }
public new string Text {
get {
return "Hello TextField!";
}
set { Number = int.Parse(value); }
}
public override void Click()
{
Console.WriteLine("In the TextField!");
}
}
This works but feels a little messy having an empty set in the Control class.
Is there a cleaner approach to this type of problem without compromising on specific property implementations on sub classes?
Many thanks,
Okay, so first thing is first, you should not be changing another property when you set a property (like you are doing to Number from Text). This is a huge code smell because it is a side effect. You should always deal directly with the properties that you intend to.
public class SelectList : Control, IGrid {
public int Number { get; set; }
public new string Text {
get {
return "Hello Select!";
}
// This is bad, someone after you may not know that this has a side effect
set { Number = int.Parse(value); }
}
}
Second, a property can be virtual just like a method, so marking your Text property as virtual and overridding in a derived class will make polymorphism work the way it is intended. "Hiding" via the new keyword would require you to cast your interface its specific class in order to get that classes implementation.
public class Control : IGrid
{
public virtual string Text
{
get { return "Hello Control!"; }
}
public virtual void Click()
{
Console.WriteLine("In the Control!");
}
}
public class SelectList : Control, IGrid
{
public int Number { get; set; }
public override string Text
{
get
{
return "Hello Select!";
}
}
public override void Click()
{
Console.WriteLine("In the Select!");
}
}
Third, you do not have to have a setter on the interface. You could just have a getter and only need to implement that.
public interface IGrid
{
string Text { get; }
void Click();
}
Finally, if you are ALWAYS going to override a method or property and NEVER going to create the base class directly (with a new) then you should consider using an abstract class if you have shared implementation (EG at least one method or property you do not change) or don't bother with the base class because you are not using any of the code anyways.
// Abstract class
public abstract class Control : IGrid
{
// Property that is not overridden but is shared
public int Number { get; set; }
public abstract string Text
{
get;
}
public abstract void Click();
}
public class SelectList : Control
{
// Don't need the Number property here, base class has it
public override string Text
{
get
{
return "Hello Select!";
}
}
public override void Click()
{
Console.WriteLine("In the Select!");
}
}
// Need everything in this class, but if it is all different anyways
// then base class is kind of a waste
public class TextField : IGrid
{
public int Number { get; set; }
public string Text
{
get
{
return "Hello TextField!";
}
}
public void Click()
{
Console.WriteLine("In the TextField!");
}
}

Overriding properties to make them readonly - what about the setter?

I have the following design goal in a class hierarchy:
There is a BaseClass defining some properties, which would usually be read/write:
public class Media
{
public virtual object Content { get; set; }
public virtual double recordingLength { get; set; }
}
The intention is to have some subclasses where this property now is readonly:
public class CompactDisk : Media
{
public override object Content
{
get { return this.getContent(); }
set {
// THERE SHOULDN'T BE A SETTER
}
}
public override double recordingLength
{
get { return 74; }
set {
// NO SETTER EITHER HERE!
}
}
}
I'm lost here, because I don't know how should I implement my design intent.
One possible approach is using interfaces.
You can split your base concept into two interfaces:
public interface IWritableMedia
{
object Content { set; }
double recordingLength { set; }
}
public interface IReadOnlyMedia
{
object Content { get; }
double recordingLength { get; }
}
And then something like CompactDisk should only implement IReadOnlyMedia:
public class CompactDisk : IReadOnlyMedia
{
public object Content { get { return ......; } }
public double recordingLength { get { return .......; } }
}
If you want to implement a CD-RW (rewritable), you should implement both interfaces:
public class RewritableCompactDisk : IReadOnlyMedia, IWritableMedia
{
public object Content { get; set; }
public double recordingLength { get; set; }
}
This way you can type your variables as IReadOnlyMedia or IWritableMedia:
IReadOnlyMedia media = new CompactDisk();
IWritableMedia media2 = new RewritableCompactDisk();
Now the issue is IWritableMedia doesn't provide getters and you don't want to declare another variable of type IReadOnlyMedia. The solution is designing a third interface called IReadWriteMedia and RewritableCompactDisk should implement it:
public interface IReadWriteMedia : IReadOnlyMedia, IWritableMedia
{
}
public class RewritableCompactDisk : IReadWriteMedia
{
public object Content { get; set; }
public double recordingLength { get; set; }
}
Since IReadWriteMedia implements IReadOnlyMedia and IWritableMedia, now you'll be able to type variables with IReadWriteMedia and access both getters and setters:
IReadWriteMedia media3 = new RewritableCompactDisk();
object content = media3.Content;
media3.Content = "hello world";
You can't, or really shouldn't, have a design where the sub types "hide" functionality of the base type. You can:
In your setters throw a NotSupportedException, or similar. This is how the Stream class behaves when you try to set the length of a stream that cannot be set.
Change your design. I don't see a way to get properties working the way you want (without resorting to "hiding", which IMHO isn't a good solution), but perhaps something like this:
public interface IMedia
{
object Content { get; }
double RecordingLength { get; }
}
public interface IWritableMedia : IMedia
{
void SetContent(object content);
void SetRecordingLength(double length);
}
Your CompactDisk would implement the just the IMedia interface, whereas a HardDrive class may choose to implement the IWritableMedia interface.

Can I override a property in c#? How?

I have this Base class:
abstract class Base
{
public int x
{
get { throw new NotImplementedException(); }
}
}
And the following descendant:
class Derived : Base
{
public int x
{
get { //Actual Implementaion }
}
}
When I compile I get this warning saying Derived class's definition of x is gonna hide Base's version of it. Is is possible to override properties in c# like methods?
You need to use virtual keyword
abstract class Base
{
// use virtual keyword
public virtual int x
{
get { throw new NotImplementedException(); }
}
}
or define an abstract property:
abstract class Base
{
// use abstract keyword
public abstract int x { get; }
}
and use override keyword when in the child:
abstract class Derived : Base
{
// use override keyword
public override int x { get { ... } }
}
If you're NOT going to override, you can use new keyword on the method to hide the parent's definition.
abstract class Derived : Base
{
// use new keyword
public new int x { get { ... } }
}
Make the base property abstract and override or use the new keyword in the derived class.
abstract class Base
{
public abstract int x { get; }
}
class Derived : Base
{
public override int x
{
get { //Actual Implementaion }
}
}
Or
abstract class Base
{
public int x { get; }
}
class Derived : Base
{
public new int x
{
get { //Actual Implementaion }
}
}
Change property signature as shown below:
Base class
public virtual int x
{ get { /* throw here*/ } }
Derived class
public override int x
{ get { /*overriden logic*/ } }
If you do not need any implementation in Base class just use abstract property.
Base:
public abstract int x { get; }
Derived:
public override int x { ... }
I would suggest you using abstract property rather than trhowing NotImplemented exception in getter, abstact modifier will force all derived classes to implement this property so you'll end up with compile-time safe solution.
abstract class Base
{
// use abstract keyword
public virtual int x
{
get { throw new NotImplementedException(); }
}
}
abstract class Base
{
public virtual int x
{
get { throw new NotImplementedException(); }
}
}
or
abstract class Base
{
// use abstract keyword
public abstract int x
{
get;
}
}
In both case you have to write in the derived class
public override int x
{
get { your code here... }
}
difference between the two is that with abstract you force the derived class to implement something, and with virtaul you can provide a default behavior that the deriver can use as is, or change.

Interfaces property name differs from class to class

Here`s the question.
public abstract class A {}
public class B:A
{
public TypeF FieldB;
}
public class C:A
{
public TypeG FieldC;
}
public class TypeF:A { }
public class TypeG:A { }
I want to have interface ex: ITypeFG and to implement it in B and C BUT to have properties names FieldB and FieldC
interface ITypeFG
{
public A FieldFG; //But i want to have names TypeF in A and TypeG in B
}
Can this be done?
Thanks.
explicit interface implementation:
public class B : A, ITypeFG
{
public TypeF FieldB { get; set; } // please don't expose public fields...
A ITypeFG.FieldFG { get { return FieldB; } }
}
public class C : A, ITypeFG
{
public TypeG FieldC { get; set; }
A ITypeFG.FieldFG { get { return FieldC; } }
}
Note that if the interface has a setter, you'll need to cast:
public class B : A, ITypeFG
{
public TypeF FieldB { get; set; }
A ITypeFG.FieldFG { get { return FieldB; } set { FieldB = (TypeF)value; } }
}
public class C : A, ITypeFG
{
public TypeG FieldC { get; set; }
A ITypeFG.FieldFG { get { return FieldC; } set { FieldC = (TypeG)value; } }
}
Two points:
Interfaces in C# can't have fields, but they can have properties.
The desired feature isn't sensible: if clients would always have to know the "specific" name of the implemented interface-property to interact with an implementation, then it isn't much of an interface is it - it's little more than a marker.
As Marc Gravell suggests, a decent workaround is to use explicit implementations. If the client has a reference to the implementing object typed as the interface, they can use the "general" name of the property. If they have a specific reference (i.e. typed as the implementing type) , they can use the "specific" name (and won't be confused by the general name since they won't see it on IntelliSense, for example).
Sounds like you should treat the field names as data along with A. That way you can keep a common interface and only vary the content of what is returned:
class Data
{
public string Name {get;set;}
public A Value {get;set;}
}
interface ITypeFG
{
Data Field {get;}
}
class B : A, ITypeFG
{
public Data Field
{
get
{
return new Data {Name = "TypeF", Value = FieldB};
}
}
}
class C : A, ITypeFG
{
public Data Field
{
get
{
return new Data {Name = "TypeG", Value = FieldC};
}
}
}

How Can I Accept a Generic Class and Use Its Properties / Methods

I want to create a class that could hold any of a number of same type of classes. For example lets says I have a base class like follows:
public class BaseClass
{
public string MyBaseString
{
get;
set;
}
}
And then I have a few derived classes like this:
public class DerivedClass : BaseClass
{
public MyDerivedClassString
{
get;
set;
}
}
public class DerivedClass2 : BaseClass
{
public MyDerivedClass2String
{
get;
set;
}
}
Now I would like a class that accepts one of these implementations and does stuff with it. Here is the only thing I can think of, but there must be a better way:
public class ClassA
{
public object MyClass
{
get;
set;
}
public ClassA (object myClass)
{
MyClass = myClass;
if (object is BaseClass)
{
//do something
}
else if (object is DerivedClass)
{
//do something specific to derived class
}
else if (object is DerivedClass2)
{
//do something specific to derived class 2
}
}
}
CLARIFICATION: The specific goal I am trying to accomplish is to use ClassA as a container class for various implementations of the BaseClass. The business goal I am trying to accomplish is to create a Legend object which might use multiple color schemes (i.e. a Mono Color Ramp, Multi Color Ramp, etc). So I would like the Legend class to contain the ColorScheme that is being used, but still have access to that color scheme's unique properties for modification later on.
CLARIFICATION 2 Based on the wide array of responses I got, I thought I'd provide an exact replication of what I'm trying to do:
public class BaseColorScheme
{
List<Color> _colors = new List<Color>();
public List<Color> Colors
{
get
{
return _colors;
}
set
{
_colors = value;
}
}
}
public class SingleColorScheme : BaseColorScheme
{
public Color MidColor
{
get;
set;
}
public SingleColorScheme( Color midColor, int numberOfClassifications )
{
Colors = CreateMonoColorRamp( midColor, numberOfClassifications );
}
}
public class MultiColorScheme : BaseColorScheme
{
public Color StartColor
{
get;
set;
}
public Color EndColor
{
get;
set;
}
public Color MidColor
{
get;
set;
}
public MultiColorScheme( Color startColor, Color endColor, Color midColor )
{
StartColor = startColor;
EndColor = endColor;
MidColor = midColor;
Colors = //do something to define multi color scheme
}
}
Then I would have a Legend Class that would be something like
public class Legend
{
public object ColorScheme
{ get; set; }
public Guid LegendId
{ get; set; }
public Legend(object colorScheme)
{
ColorScheme = colorScheme;
}
}
Finally I might have a form that sits on top of the legend that displays the properties of the various color schemes based on which type of color scheme it is. Hopefully that helps clarify a bit.
public class ClassA<T> where T : BaseClass
{
public T MyClass { get; set; }
public ClassA(T myClass) { MyClass = myClass; }
}
Beyond that, define the common interface of the class hierarchy either as an interface or as methods (concrete, abstract, or virtual) within the base class. Then you can be assured all derived classes have such method / properties and can use them within your generic wrapper.
Instead of letting ClassA perform whatever needs to be done, you can use polymorphism and let the classes do it to themselves.
Simply declare a virtual method in the base class, have it do whatever you need it do so, and then override this method in the subclasses. In the method in ClassA, you just need to call that method on the object you receive as a parameter - without having to care about the specific type.
If you need to access different properties based on which derived class is passed something like this should help:
public class ClassA<T> where T : BaseClass
{
public T MyClass { get; set; }
public ClassA(T myClass) { MyClass = myClass; }
public void DoStuffToMyClass()
{
if(MyClass is BaseClass)
{ // do base class stuff }
else if(Myclass is DerivedClass)
{ // do DerivedClass stuff }
else if(MyClass is DerivedClass2)
{ // do DerivedClass2 stuff }
}
}
This gives you the type saftey to ensure you at least have the BaseClass object, and possibly a derived class.
The answer is polymorphism, let the object do it themselves.
public class BaseClass
{
public string MyString { get; set; }
public virtual string DoIt()
{
return "I'm Base Class";
}
}
public class DerivedClassA
{
public override string DoIt()
{
return "I'm Derived Class A";
}
}
public class DerivedClassB
{
public override string DoIt()
{
return "I'm Derived Class B";
}
}
....
public ClassA (BaseClass myClass)
{
MyClass = myClass;
MyClass.DoIt();
}
.....
ClassA x1 = ClassA(new BaseClass()) // calls BaseClass.DoIt()
ClassA x2 = ClassA(new DerivedClassA()) // calls DerivedClassA.DoIt()
ClassA x3 = ClassA(new DerivedClassB()) // calls DerivedClassB.DoIt()
whenever you catch yourself acting differently based on the run-time type of the object, you are dealing with code that breaks OO principles, i.e. a class that does not respect the base class contract.
Can you use virtual methods?
public abstract class BaseClass
{
public abstract void DoStuff();
}
public class DerivedClass1 : BaseClass
{
public override void DoStuff()
{
...
}
}
public class DerivedClass2 : BaseClass
{
public override void DoStuff()
{
...
}
}
Without generics:
public class ClassA
{
public BaseClass MyClass
{
get;
set;
}
public ClassA (BaseClass myClass)
{
MyClass = myClass;
myClass.DoStuff();
}
}
or with generics:
public class ClassA<T> where T : BaseClass
{
public T MyClass { get; set; }
public ClassA (T myClass)
{
MyClass = myClass;
myClass.DoStuff();
}
}
Keep it simple: polymorphism
Hopefully your objects have a common interface, something like:
class Base {
public virtual void DoSomething() { /* Default implementation */ }
}
class Derived1 : Base {
public override void DoSomething() { /* Implementation specific to this type */ }
}
class Derived2 : Base {
public override void DoSomething() { /* Another implementation specific to this type */ }
}
Or maybe they implement a common interface. So hopefully your consuming class can hold the most general representation of your inputs as possible and invoke code as such:
class Dependent {
public Dependent(Base instance) {
instance.DoSomething();
}
}
So your Dependent class doesn't really are whether it has a derived type or a base type.
Not quite as simple: visitor pattern
Sometimes polymorphism doesn't really work, which is particularly the case if you need to access the specific members of your derived classes, and those members aren't in the base class. Visitor pattern works well in this case, especially if you have a fixed, well-defined graph of objects.
public interface IVisitor<T> {
T Visit(Base x);
T Visit(Derived1 x);
T Visit(Derived2 x);
}
class Base {
public virtual T Accept<T>(IVisitor<T> visitor) { visitor.Visit(this); }
public string BaseString { get; set; }
}
class Derived1 : Base {
public override T Accept<T>(IVisitor<T> visitor) { visitor.Visit(this); }
public string Derived1String { get; set; }
}
class Derived2 : Base {
public override T Accept<T>(IVisitor<T> visitor) { visitor.Visit(this); }
public string Derived2String { get; set; }
}
So Derived1 and Derived2 have a different set of properties, and if you need to get to those properties without a runtime type-checking, implement a visitor:
class DefaultStringVisitor : IBaseVisitor<string> {
public string Visit(Base x) { return x.BaseString; }
public string Visit(Derived1 x) { return x.Derived1String; }
public string Visit(Derived2 x) { return x.Derived2String; }
}
class Dependent {
public Dependent(Base x) {
string whatever = x.Accept<string>(new DefaultStringVisitor());
}
}
So the visitor pattern gives you access to your derived object's members without a type-check. Its a somewhat inflexible pattern (i.e. need to know which objects to visit up front), but it might work for your needs.

Categories

Resources