This may be a beginner question but is there a standard way to refactor the duplication of the Wheel property into the abstract class yet still maintain the explicit cast to the Part type. Let’s assume we have to prevent a FastCarWheel from being put on a SlowCar, and that there are many properties just like this one.
abstract class Car {}
class FastCar : Car
{
public FastCarWheel Wheel { get; set; }
}
class SlowCar : Car
{
public SlowCarWheel Wheel { get; set; }
}
abstract class WheelPart {}
class FastCarWheel: WheelPart {}
class SlowCarWheel: WheelPart {}
In this type of scenario is it common to just allow this type of duplication? I was thinking of making use of Generics but it just seems like I’m moving the issue around, and it gets worse for each additional property that behaves this way.
abstract class Car <P>
where P : Part
{
protected abstract P Wheel { get; set; }
}
Thanks
I think using a Fast or Slow policy can help put the correct wheel for a given car type (where both Car and Wheel are dependent on the policy and a Car object has, say, a private aggregration of wheels).
This solution isn't polymorphic, but might be your only option if you need visibility at the base class level:
abstract class Car
{
private CarWheel wheel;
public CarWheel Wheel
{
get { return wheel; }
protected set { wheel = value; }
}
}
class FastCar : Car
{
public new FastCarWheel Wheel
{
get { return base.Wheel as FastCarWheel; }
set { base.Wheel = value; }
}
}
class SlowCar : Car
{
public new SlowCarWheel Wheel
{
get { return base.Wheel as SlowCarWheel ; }
set { base.Wheel = value; }
}
}
You might want to evaluate if your base class is doing too much. It might be possible to solve your problem by splitting your classes in to many smaller classes. On the other hand, sometimes it's unavoidable.
Since your goal appears to be allowing the client code to get the property back as a WheelPart, but only set it as a specific subclass you have a couple of options. Though I'm afraid that neither of them are very clean.
Firstly you could throw a runtime error if the wrong type is set:
public abstract class Car
{
public abstract WheelPart Wheel { get; set; }
}
public class FastCar : Car
{
private FastWheel _wheel;
public override WheelPart Wheel
{
get { return _wheel; }
set
{
if (!(value is FastWheel))
{
throw new ArgumentException("Supplied wheel must be Fast");
}
_wheel = (FastWheel)value;
}
}
}
But I wouldn't do this as it is very unclear to the client code that any other type of wheel will throw an exception, and they'll get no compiler feedback.
Otherwise you could separate out the Getter and Setter for the property so that the type required is very clear:
public abstract class Car
{
public abstract WheelPart Wheel { get; }
}
public class FastCar : Car
{
private FastWheel _wheel;
public override WheelPart Wheel
{
get { return _wheel; }
}
public void SetWheel(FastWheel wheel)
{
_wheel = wheel;
}
}
This is much clearer to the client and IMHO a nicer solution if you absolutely must expose the getter as the base WheelPart class.
I would create an ICar and then define your Cars that way, instead of an abstract class
interface ICar
{
IWheel Wheel {get; set;}
}
class FastCar: ICar
{
FastWheel fastWheel;
IWheel Wheel
{
get { return fastWheel; }
set
{
if (value is FastWheel) fastWheel = (FastWheel)value;
}
}
}
class SlowCar: ICar
{
SlowWheel slowWheel;
IWheel Wheel
{
get { return slowWheel; }
set
{
if (value is SlowWheel ) slowWheel = (SlowWheel )value;
}
}
}
class FastWheel: IWheel {}
class SlowWheel: IWheel {}
Define a wheel interface (IWheel):
public interface IWheel
{
}
Implement the interface for FastCarWheel and SlowCarWheel eg
public class FastCarWheel : IWheel
{
}
Now your abstract class becomes:
abstract class Car
{
public IWheel Wheel { get; set; }
}
Subclasses of Car are then free to use whatever implementation of Wheel they choose:
FastCar fastCar = new FastCar();
fastCar.Wheel = new FastCarWheel();
Related
i'm trying to build a sort of framework for some base process in an app. There is some common behavior where i have to execute some operations but these operations are different depending on some scenarios. I have done something i'm not sure if it's considered a bad practice to make something like this:
public interface IMyDto
{
string makerIdentifier { get; set; }
}
public class DtoOne:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteOne
}
public class DtoTwo:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteTwo
}
public abstract class AbstractMaker
{
public abstract void DoSomething(IMyDto myInterface);
}
public class ConcreteMakerOne:AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoOne;
// If concrete is not null..do stuff with DtoOne properties
}
}
public class ConcreteMakerTwo : AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoTwo;
// If concrete is not null..do stuff with DtoTwo properties
}
}
public class Customer
{
public void MakeSomething(IMyDto myDto)
{
var maker = GetMaker();
maker.DoSomething(myDto);
}
private AbstractMaker GetMaker()
{
//Stuff to determine if return ConcreteOne or ConcreteTwo
}
}
The code im not happy with is the:
var concrete = myInterface as DtoOne;
I would appreciate a lot if someone could give me some advide or tips about a pattern or good oop practice for this scenario.
It's not clear what all of your use cases are, but one option might be generics:
public abstract class AbstractMaker<T> where T:IMyDto
{
public abstract void DoSomething(T myInterface);
}
public class ConcreteMakerTwo : AbstractMaker<DtoTwo>
{
public override void DoSomething(DtoTwo myInterface)
{
// now you are certain that myInterface is a DtoTwo
}
}
I am not sure if I understand correctly what are you asking about, but why not just put method DoSomething in IMyDto and implement it differently in DtoOne, DtoTwo, etc.? There would be only one Maker and would always call the same method.
is there any way to use interfaces as navigation properties in EF6?
I've found related topics for EF4 or earlier where it didn't seem to be possible; generally, inheritance seems to have improved a lot since then, but I haven't found a way to make this specific problem work yet.
Example:
public interface IPerson
{
string name { get; set; }
}
public class Man : IPerson { /* ... */ }
public class Woman : IPerson { /* ... */ }
public interface ICar
{
IPerson driver { get; set; }
}
public class Car : ICar
{
public virtual IPerson driver { get; set; } // This won't map
}
Is this possible in any way? If not, what'd be an advisable way to do this?
Because currently I don't see any way for an interface to have a set-able property whose type is some other interface (the IPerson property of ICar, for example), which kind of strikes me as a very serious design limitation?!
Okay, for those possibly facing the same issue in the future. After more testing around, this is how I'm doing it now.
public interface IPerson
{
string name { get; set; }
}
public abstract class APerson : IPerson
{
public string name { get; set; }
}
public class Man : APerson { /* ... */ }
public class Woman : APerson { /* ... */ }
public interface ICar
{
IPerson driver { get; set; }
}
public class Car : ICar
{
// This maps to the database
public virtual APerson driver { get; set; }
// And this implements the interface
ICar.driver
{
get
{
return (IPerson)driver;
}
set
{
if(!(value is APerson))
throw new InvalidCastException("driver must inherit from APerson");
driver = (APerson)value;
}
}
}
This gets a bit more tricky when having one-to-many / many-to-many relations, for that case I've written a class that inherits from Collection<Interface type>, but also implements ICollection<Abstract base type>, and again throws an exception when someone tries adding/setting any object that doesn't inherit from the abstract base class. It's basically a Collection<IPerson> that's guaranteed to only contain objects inheriting that inherit APerson, if you will.
This solution is definitely not ideal, because it just throws an exception if somebody tries assigning a value to driver that does not inherit from APerson, so no compile-time safety here.
But it's the best solution I could think of so far, if you really want to keep your interfaces separate and self-contained.
I am currently in the middle of self-teaching some basic concepts of C# and I am experimenting with abstract classes and polymorphism. I thought I got the basic concept but it turned out that the concept doesn't work like I understood it :). However - I hope I get some answers which clear the dust a little bit :).
The whole task I am trying to achieve is to extend an abstract base class and use the extension with an object of the base class. Like here:
I have an abstract class which implements an abstract property like:
public abstract class BaseClass
{
public abstract MyProperty mP{get;}
}
where the property is
public abstract class MyProperty
{
public abstract string PropertyName{get;}
}
Now I am deriving the MyProperty class for an actual implementation like
public class DerivedProperty : MyProperty
{
public override string PropertyName
{
get
{
return this._name;
}
}
private _name = "Property1";
/* some other implementation follows here...... */
}
As I've understood polymorphism and inheritance it should now be possible to instantiate a derived class from BaseClass and override the property MyProperty with an object of DerivedProperty like this:
public class DerivedClass : BaseClass
{
public override DerivedProperty mP
{
get
{
return dP;
}
}
private DerivedProperty dP = new DerivedProperty();
/* more implementation follows here...... */
}
Because DerivedProperty is an object of MyProperty and DerivedProperty at the same time it is possible to use it where either MyProperty or DerivedProperty is referenced. At least that's what I thought but it seems that this is wrong.
Now I am wondering - why is polymorphism so useful when something like above is not possible? Because even when I try something like this:
public class DerivedClass : BaseClass
{
public override MyProperty mP
{
get
{
return dP as DerivedProperty;
}
}
private DerivedProperty dP = new DerivedProperty();
/* more implementation follows here...... */
}
I still get only my base object MyProperty and not my extended object DerivedProperty which I want to get.
I know why I get those results - I just don't seem logical to me :). Is it really like polymorphism is supposed to work or is my implementation just crap and I have to do it in a different way to get my extended property?
Appreciate your help here!
You have to provide the same type for overrided property. You can use it later in your abstract BaseClass. Parameters as well as return value of member have to be the same when overriding. It is usually not a problem.
I've prepared following examples that my code look similar to yours.
In some scenarios I've seen that there is added second property with more specific type and different (more specific) name:
public abstract class BaseCar
{
public abstract BaseDriver Driver { get; }
}
public abstract class BaseDriver
{
public abstract string Name { get; set; }
}
public class AgressiveDriver : BaseDriver
{
public override string Name { get; set; }
}
public class FastCar : BaseCar
{
private AgressiveDriver _agressiveDriver = new AgressiveDriver();
public override BaseDriver Driver { get { return _agressiveDriver; } }
public AgressiveDriver AgressiveDriver { get { return _agressiveDriver; } }
}
Second approach is to use generics:
public abstract class BaseCar<TDriver>
where TDriver : BaseDriver
{
public abstract TDriver Driver { get; }
}
public abstract class BaseDriver
{
public abstract string Name { get; set; }
}
public class AgressiveDriver : BaseDriver
{
public override string Name { get; set; }
}
public class FastCar : BaseCar<AgressiveDriver>
{
private AgressiveDriver _agressiveDriver = new AgressiveDriver();
public override AgressiveDriver Driver { get { return _agressiveDriver; } }
}
but I think first approach is better because there is no problem with creating/using BaseCar objects (for example to create BaseCar<> variable you have to specify type parameter). Also it makes sense to create more specific name for more specific property.
I think you have an extra bit of complexity you don't need. You have an abstract class inside an abstract class. If you are just learning/relearning this you have skipped a couple easy steps for understanding. Here's a simpler example to start with.
public abstract class Shape
{
public abstract double GetArea();
public abstract double Circumference();
}
public class Square: Shape
{
public double width {get; set;}
public override double GetArea()
{
return width * width;
}
public override Circumference()
{
return width * 4;
}
}
You can now instantiate a Square or create a Circle Class and be able to use either where you use Shape.
I'm trying to create two interface hierarchies, one for the business model objects and one for the ui. I know it's important to have loose coupling between the layers but part of the application will require drawing diagrams so I need the model objects to be readily available to their corresponding graphical representations and I have a common layer holding interfaces for the model objects..
Common class library code:
public interface IBase {}
public interface IBookObject : IBase {}
public interface ITapeObject : IBase {}
public class Book : IBookObject {}
Graphics layer code:
public interface IModelObject<T>
{
T ModelObject { get; set; } // might be a book or tape , etc
}
public class GraphicObject<T> : IModelObject<T>
{
public T ModelObject { get; set; }
}
Code use:
IBookObject bk = new Book();
var go = new GraphicObject<IBookObject>(); // will fail later
//var go = new GraphicObject<IBase>(); // will succeed later
go.ModelObject = bk;
if (go is IModelObject<IBase>) // can't use is IModelObject<IBookObject>
// as go might be GraphicObject<ITapeObject>
{
Debug.WriteLine("Success");
}
So if I want to test for IBase (and then access ModelObject), I have to make sure that the original object was created with IBase and not a derived interface, and this seems like a cause of bugs later. my questions are:
1) Am I doing something horrible?! :) I might be overlooking a better approach..
2) failing that, is there some way of using the new contravariance c# 4 techniques to make the is line test for any interface deriving from IBase? Alternatively I think it would work if IBook didn't inherit from IBase, but Book (and Tape) implemented both IBook and IBase separately.
3) failing that, is there any way to prevent construction of GraphicObject<IBookObject>() and GraphicObject<ITapeObject>()?
Thank you!
Would this work?
public interface IBase { }
public interface IBookObject : IBase { }
public interface ITapeObject : IBase { }
public class Book : IBookObject { }
public interface IModelObject
{
IBase ModelObject { get; set; } // might be a book or tape , etc
}
public class GraphicObject<T> : IModelObject
where T: class, IBase
{
public T ModelObject { get; set; }
#region IModelObject Members
IBase IModelObject.ModelObject
{
get
{
return ModelObject;
}
set
{
ModelObject=value as T;
}
}
#endregion
}
class Program
{
static void Main(string[] args)
{
IBookObject bk=new Book();
var go=new GraphicObject<IBookObject>(); // will fail later
//var go = new GraphicObject<IBase>(); // will succeed later
go.ModelObject=bk;
if(go is IModelObject) // can't use is IModelObject<IBookObject> as go might be GraphicObject<ITapeObject>
{
Debug.WriteLine("Success");
}
}
}
I m writing interfaces for new project and would like to get some advice.
I have a class that have a subclass and it has a subclass. The tree of this classes is like this:
Class Car
{
Wheels Wheel;
}
Class Wheels
{
Rims Rim;
}
So to simplify: one car has one wheel and one wheel has one rim. (cant make up other better example, sorry).
So I would like to force this hierarchy in my interface implementation of ICar, IWheels and IRims.
So i did something like this (in C#):
ICar
{
IWheels Wheel;
}
IWheels
{
IRims Rim;
}
And i have a error that I can not have fields in interface implementation. So this started me thing that maybe it's wrong interface design. I would like to force interface implementations to implement this kind of hierarchy. But maybe accorting to design patterns and best practices it should be done in other way?
Could you please tell me how to design my system so that objects will be forced to implement this kind of hierarchy?
Maybe there is something not precise in my question or I missing some important info. If yes, please ask in comments.
In your interface, you'll have to make it clear that Wheels should be a property of ICar, since you cannot declare which fields an interface implementation should have. (Fields are inner workings, so the interface should not know about it).
interface ICar
{
IWheels Wheels
{
get;
}
}
You can't specify a field in an interface (and you shouldn't be able to - that's an implementation decision) but you can specify a property:
public interface ICar
{
IWheels Wheel { get; set; }
}
public interface IWheels
{
IRims Rim { get; set; }
}
You may well want to only put the getter in the interface though - it's slightly unusual to include a setter in an interface:
public interface ICar
{
IWheels Wheel { get; }
}
public interface IWheels
{
IRims Rim { get; }
}
(There are oddities if you want to override an existing (or abstract) property which only has a getter to add a setter, but it's okay to implement a "getter-only" interface with setters as well, I believe.)
You can't declare fields, but you can declare properties. That will have the same end effect of forcing a particular class to provide an instance of another class.
ICar
{
IWheels Wheel { get; set; }
}
IWheels
{
IRims Rim { get; set; }
}
As the error says, you can't specify fields in your interfaces. You can specify properties though:
interface ICar
{
IWheels Wheel { get; set; }
}
interface IWheels
{
IRims Rim { get; set; }
}
I'm not so much used to C# but it sounds to me that you can force that implementation by making Abstract classes, with the fields you want to use.
So if you extend those abstract classes you will have the fields in them available.
You'll have to make an abstract class AND an interface though...
Here it is a fully functional code...
Hope it helps...
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication10
{
//Interfaces
public interface ICar
{
string name { get;}
IWheel wheel { get;}
}
public interface IWheel
{
string brand { get;}
}
//Implementations
public class Michelin : IWheel
{
#region IWheel Members
public string brand
{
get { return "michelin"; }
}
#endregion
}
public class Toyota : ICar
{
Michelin m = new Michelin();
#region ICar Members
public string name
{
get { return "toyota"; }
}
public IWheel wheel
{
get { return m; }
}
#endregion
}
//A user of the interfaces. Only cares about ICar but knows implicitly about IWheel
public class Stand
{
public Stand()
{
cars = new List<ICar>(2);
cars.Add(new Toyota());
cars.Add(new Toyota());
}
List<ICar> cars;
public string ShowCars()
{
StringBuilder str = new StringBuilder();
foreach (ICar iterCar in cars)
{
str.AppendLine(string.Format("car {0} with wheel {1}",
iterCar.name, iterCar.wheel.brand));
}
return str.ToString();
}
}
//entry point. creates a stand and shows the cars, testing that properties are visible
class Program
{
static void Main(string[] args)
{
Stand myLittleStand = new Stand();
Console.WriteLine(myLittleStand.ShowCars());
}
}
}