I hope my question is legit because i'm not really used to all the hierarchical class structs.
I try to encapsulate a class that delivers the same functions for two different cameras connected to device. Those functions are thought to be within the class DeviceObject whilst I want to access those functions by using an instance of Camera1 or Camera2. Here's some pseudo code that might not work:
public class Camera1 : DeviceObject
{
public Generic.CameraSelect Camera { get; set; } = Generic.CameraSelect.CAM1;
}
public class Camera2 : DeviceObject
{
public Generic.CameraSelect Camera { get; set; } = Generic.CameraSelect.CAM2;
}
public class DeviceObject
{
public void SomeFunction()
{
HardwareDriver.Function(SelectedCamera);
}
}
What I want is to easly access the methods of DeviceObject dependend on the Camera-Class:
public void Method()
{
Camera1 Cam1 = New Camera1();
Camera2 Cam2 = New Camera2();
Cam1.SomeFunction();
Cam2.SomeFunction();
}
I apologize if this is a stupid question but after 7 hours of programming I'm completely stuck and don't get it in my head anymore :)
UPDATE:
I have implemented - as entirely all of you have recommended - an abstract base class and derivate the Camera Objects as member of the base class.
What I didn't know so far, that it's possible to cast derived classes to the type of base classes. That was absolutely new to me but helped me a looot! with my implementation.
So thanks to all of you who helped me without minusing me to hell :)
Why not use an abstract class?
public class Camera1 : Camera
{
public override Generic.CameraSelect CameraType { get; set; } = "CAM1";
}
public class Camera2 : Camera
{
public override Generic.CameraSelect CameraType { get; set; } = "CAM2";
}
public abstract class Camera
{
public abstract Generic.CameraSelect CameraType { get; set; }
public void SomeFunction()
{
HardwareDriver.Function(this);
}
}
You typically only use inheritance when you need different implementation (methods). If the implementation is the same for both cameras but the data involved is different, you can use one class and a factory to "create" a camera with the appropriate settings.
public class CameraFactory
{
public static Camera1 {
get {
return new Camera {Camera = Generic.CameraSelect.CAM1};
}
public static Camera2 {
get {
return new Camera {Camera = Generic.CameraSelect.CAM2};
}
}
That's not the only way to do it, but it is one way.
Also note that if the Camera property should not change then make it get-only (or at worst use a private setter.
As other people have suggested, the answer to your question is probably to add an abstract / override:
public class Camera1 : Camera
{
public override Generic.CameraSelect CameraType { get; set; } = "CAM1";
}
public class Camera2 : Camera
{
public override Generic.CameraSelect CameraType { get; set; } = "CAM2";
}
public abstract class Camera
{
public abstract Generic.CameraSelect CameraType { get; set; }
public void SomeFunction()
{
HardwareDriver.Function(this);
}
}
However, I was triggered by the HardwareDriver class. There are two points I'd like to make here:
Drivers work on capabilities, not on names. If you're goal is decomposition, you might want to go for a double dispatch that calls stuff depending on the scope.
What's the purpose of a camera and why is it modelled the way 'the world' works?
Double dispatch
Let's start with the double dispatch. The way I see it, you'll probably end up with a large 'switch' block somewhere that incorporates the logic. That doens't make a lot of sense to me. Basically you probably attempt to decouple the objects from the logic -- so let's use inheritance to do that. In this case, it'll work like this:
public class Camera1 : Camera
{
public override void SomeFunction(IDeviceVisitor driver)
{
// Very simple camera:
driver.HandleAngle(this, 12.0);
driver.GenerateModel();
}
}
public class Camera2 : Camera
{
public override void SomeFunction(IDeviceVisitor driver)
{
// This camera understands focus
driver.HandleAngle(this, 12.0);
driver.HandleFocus(this, focus, this.focus * 1.2);
driver.GenerateModel();
}
}
public class SomeHardwareDriver : IDeviceVisitor { ... }
public interface IDeviceVisitor
{
void HandleFocus(Camera camera, double focusValue, double realDistance);
void HandleAngle(Camera camera, double angle);
void GenerateModel();
// [...]
// etc
}
public abstract class Camera
{
public abstract void SomeFunction(IDeviceVisitor driver);
}
The reason I pass this along is because you might want to call another camera function from within the HardwareDriver to do the magic.
Modelling in the way the world works
If two camera have nothing with each other in common, don't give them a common base class. It makes no sense.
Or the more general rule: always remember that a class model doesn't need to make sense to you as a person; it has to make sense to a computer.
How to know when you're running the wrong way
2 clues:
If you end up with large switch blocks, a lot of if-then-else's, etc -- then you're probably doing it wrong.
If you copy-paste code, you're probably doing it wrong.
You can have a encapsulating method which accepts a parameter of DeviceObject like
public void CallSomeFunction(DeviceObject dobj)
{
dobj.SomeFunction();
}
Then you can create an instance of any of camera base type and call the method
Camera1 Cam1 = New Camera1();
CallSomeFunction(cam1);
Related
I am faced with a C# design problem that C#'s limitations are making hard to achieve. I need some sort of design pattern/strategy to rescue me.
I must create the archetypical set of abstract shape classes: Base class Shape with derived classes LineShape, RectShape, etc. Specific implementations will derive from these. The problem is that I really need to use classes here, not interfaces and this is forcing me to duplicate a lot of code.
To illustrate:
public abstract class Shape
{
public abstract int Id { get; } // Unique ID
public abstract string Name { get; set; } // Shape name. Defaults to the type of shape
public abstract bool IsLocked { get; set; } // May the user change this shape in any way?
}
public abstract class LineShape : Shape
{
public abstract Point P1 { get; set; }
public abstract Point P2 { get; set; }
}
public abstract class CircleShape : Shape
{
public abstract Point Center { get; set; }
public abstract double Radius { get; set; }
}
When I start creating the derived implementations (LineImpl, CircleImpl, etc), I find that the implementations of the Shape functions are identical for all the Impl classes, yet specific enough that I cannot implement them in the abstract Shape class itself.
So I need to find a way to share a common implementation of these function in my derived hierarchy.
In other words LineImpl must derive from LineShape. CircleImpl must derive from CircleShape, etc. I cannot find a way to insert a ShapeImpl in there to handle the boiler plate stuff. So I am forced to implement all those Shape functions over and over again, once in each Impl shape type.
I tried using generics to get my way out of this but unfortunately a generic class cannot specify its base class with a generic argument. In other words, the following approach (which I might do in C++) does not work in C#
public class ShapeImpl<TBase> : T where T : Shape { ... boiler plate implemented here)...}
public class LineImpl : ShapeImpl<LineShape> { }
public class CircleImpl : ShapeImpl<CircleShape> { }
So I am at a loss. Is there some C# trick or design pattern that can get me out of this? Or am I forced to implement the same functions multiple times?
yet specific enough that I cannot implement them in the abstract Shape class itself.
You also mentioned:
I find that the implementations of the Shape functions are identical for all the Impl classes
I think that this is classic case of over-thinking for future implementation. if you say- the implementation is identical for all classes, I wouldn't bother too much over thinking for something in the future that may never arrive.
But, if you insist, you may implement it in the following way:
public abstract class Shape
{
public abstract int Id { get; } // Unique ID
public abstract string Name { get; set; } // Shape name. Defaults to the type of shape
public abstract bool IsLocked { get; set; } // May the user change this shape in any way?
public abstract void Foo();
}
public abstract class SepcificShape : Shape
{
protected virtual void FooSpecific()
{
Console.WriteLine("Specific Implementation");
}
}
public abstract class LineShape : SepcificShape
{
public abstract Point P1 { get; set; }
public abstract Point P2 { get; set; }
}
public class LineImp : SepcificShape
{
public override int Id { get; }
public override string Name { get; set; }
public override bool IsLocked { get; set; }
public override void Foo()
{
base.FooSpecific();
}
}
The only way to achieve something similar to multiple inheritance in C# I can think of would be to use default interface implementations, e.g. like this:
interface IShapeSdk
{
string GetNameSdk() => "Shape SDK name";
}
abstract class Shape
{
public abstract string GetName();
}
class ShapeImpl : Shape, IShapeSdk
{
public override string GetName()
{
return ((IShapeSdk)this).GetNameSdk();
}
}
This way all shapes will inherit from Shape, but only the external-SDK-shapes will inherit the common logic defined in IShapeSdk.
Not the cleanest approach, and a lot of C# developers are against the usage of this relatively new feature (which by the way is available only in C# 8 and above and .NET Core 3.0 and above).
Actually,I work an application about map simulation,Element represent something with id and name:
public abstract class Element
{
public string Id { get; set; }
public string Name { get; set; }
public abstract void Display();
public abstract void Stop();
public abstract void Refresh();
}
And Device is something like radar or radio device,they all have id and class,so Device inherit Element:
public abstract class Device:Element
{
}
and Target calss is something like radar station,radio station with a position property,
public class Target : Element
{
public Position Position { get; set; }
public List<Device> Devices { get; private set; }
public List<Target> Targets { get; private set; }
public override void Display()
{
//throw new NotImplementedException();
}
public override void Refresh()
{
//throw new NotImplementedException();
}
public override void Stop()
{
//throw new NotImplementedException();
}
}
Position is a struct :
public struct Position
{
public double Lat { get; set; }
public double Lng { get; set; }
public Position(double lat, double lng)
{
Lat = lat;
Lng = lng;
}
}
There is also a class named Platform inherit Target,which means a ship or a plane,they can move from one position to another.
public class Platform : Target
{
public double Speed { get; set; }
public void Move()
{
}
}
All these classes should be in BL,that's no problem.But in UI, Device or Target should have Color and image proerty to show in map control(GMap.net,use image to GMapMarker).For the reason of split ui from bl,image or color will not allowed in BL.The question is:
Is there some design patterns or elegant way to handle this situation?
Thanks!
Design patterns provide general solution to commonly occurring design problem.
I would like you to follow below approach.
Understand intent of each pattern
Understand checklist or use case of each pattern
Think of solution to your problem and check if your solution falls
into checklist of particular pattern
If not, simply ignore the design-patterns and write your own solution.
Useful links:
https://sourcemaking.com/design_patterns: Explains intent, structure and checklist beautifully in multiple languages including C++ and Java
wikipedia : Explains structure, UML diagram and working examples in multiple languages including C# and Java .
Check list and Rules of thumb in each sourcemakding design-pattern provides alram bell you are looking for.
As per your requirement I think Repository Design pattern is best for you.
If you want to assign image and color to an element then you may have them in model(in your Element class). Initially they would be null but later you may assign them values. I suppose your models are shared between BL and UI.
This question sounds very common, but I have no idea how i should implement it.
My scenario:
Question: How to implement DirectionTile?
Behavior implementation of DirectionTile:
abstract class DirectionTile
{
public Point Direction;
public Tile Next => Board.GetTile(Coords + Direction);
}
As you can see property Coords will be from the base class (?), which is Tile.
Both RailTile and SailTile are DirectionTiles. However, I can not just inherit from DirectionTile, as SailTile needs to inherit from WaterTile and this would case 2 relations with Tile (really want to use polymorphism like this).
I hope somebody can help me with this problem, that I can not solve. Let me know if my explanation is clear enough.
If i understand correctly, DirectionTile is a behaviour implemented by entity.
Use simply an Interface IDirectionTile, and to prevent multiple implementation you could provide an extension Methods :
public interface IDirectionTile
{
}
public static class TileExtensions
{
public static void GetDirection(this IDirectionTile th)
{
}
public static void Next(this IDirectionTile th)
{
}
}
Do it like this: Base from your diagram Tile will be your base/parent class and all other classes will be its child class. which then will inherit the property and function(s) that the Tile has. For DirectionTile i think it's a separate entity/class where you will just instantiate WaterTile and RailTile
public abstract class Tile
{
private Point direction;
public Point Direction
{
get { return direction; }
set { direction = value; }
}
public abstract string someFunction();
}
Now to inherit the property and the function:
public class WaterTile : Tile
{
//all property and functions now are accessible from the Tile base class
private string somevariable;
public string Somevariable
{
get{return somevariable;}
set{somevariable=value;}
}
public override string someFunction()
{
//return "something";
}
}
public class SailTile : WaterTile
{ //if there are additional properties/functions in your WaterTile it will be accessible by this class (SailTile) but not to other class
//in this case Somevariable is accessible in this class
}
Is it possible to define an interface in C# which has a default implementation? (so that we can define a class implementing that interface without implementing that particular default method).
I know extension methods (as explained in this link for example). But that is not my answer because having a method extension like the following, the compiler still complains about implementing MyMethod in MyClass:
public interface IMyInterface
{
string MyMethod();
}
public static class IMyInterfaceExtens
{
public static string MyMethod(this IMyInterface someObj)
{
return "Default method!";
}
}
public class MyClass: IMyInterface
{
// I want to have a default implementation of "MyMethod"
// so that I can skip implementing it here
}
I am asking this because (at least as far as I understand) it is possible to do so in Java (see here).
PS: having an abstract base class with some method is also not my answer simply because we don't have multiple inheritance in C# and it is different from having a default implementation for interfaces (if possible!).
C# v8 and above allows concrete method implementation in interfaces as well. This will allow your concrete implementation classes to not break when you change the interfaces being implemented in future.
So something like this is now possible:
interface IA
{
void NotImplementedMethod(); //method having only declaration
void M()
{
WriteLine("IA.M");
}//method with declaration + definition
}
Please refer to this GitHub issue # 288. Also Mads Torgersen talks about this feature at length in this channel 9 video.
MS Docs - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods
I develop games so I often want to have common function for all implementations of an interface but at the same time allow each implementation to do its own thing as well, much like a subclass' virtual / override methods would function.
This is how I do it:
public class Example
{
void Start()
{
WallE wallE = new WallE();
Robocop robocop = new Robocop();
// Calling Move() (from IRobotHelper)
// First it will execute the shared functionality, as specified in IRobotHelper
// Then it will execute any implementation-specific functionality,
// depending on which class called it. In this case, WallE's OnMove().
wallE.Move(1);
// Now if we call the same Move function on a different implementation of IRobot
// It will again begin by executing the shared functionality, as specified in IRobotHlper's Move function
// And then it will proceed to executing Robocop's OnMove(), for Robocop-specific functionality.
robocop.Move(1);
// The whole concept is similar to inheritence, but for interfaces.
// This structure offers an - admittedly dirty - way of having some of the benefits of a multiple inheritence scheme in C#, using interfaces.
}
}
public interface IRobot
{
// Fields
float speed { get; }
float position { get; set; }
// Implementation specific functions.
// Similar to an override function.
void OnMove(float direction);
}
public static class IRobotHelper
{
// Common code for all IRobot implementations.
// Similar to the body of a virtual function, only it always gets called.
public static void Move(this IRobot iRobot, float direction)
{
// All robots move based on their speed.
iRobot.position += iRobot.speed * direction;
// Call the ImplementationSpecific function
iRobot.OnMove(direction);
}
}
// Pro-Guns robot.
public class Robocop : IRobot
{
public float position { get; set; }
public float speed { get; set;}
private void Shoot(float direction) { }
// Robocop also shoots when he moves
public void OnMove(float direction)
{
Shoot(direction);
}
}
// Hippie robot.
public class WallE : IRobot
{
public float position { get; set; }
public float speed { get; set; }
// Wall-E is happy just moving around
public void OnMove(float direction) { }
}
Short Answer:
No, you cannot write implementation of method in interfaces.
Description:
Interfaces are just like contract ,so that the types that will inherit from it will have to define implementation, if you have a scenario you need a method with default implementation, then you can make your class abstract and define default implementation for method which you want.
For Example:
public abstract class MyType
{
public string MyMethod()
{
// some implementation
}
public abstract string SomeMethodWhichDerivedTypeWillImplement();
}
and now in Dervied class:
public class DerivedType : MyType
{
// now use the default implemented method here
}
UPDATE (C# 8 will have support for this):
C# 8 will allow to have default implementation in interfaces
Not directly, but you can define an extension method for an interface, and then implement it something like this
public interface ITestUser
{
int id { get; set; }
string firstName { get; set; }
string lastName { get; set; }
string FormattedName();
}
static class ITestUserHelpers
{
public static string FormattedNameDefault(this ITestUser user)
{
return user.lastName + ", " + user.firstName;
}
}
public class TestUser : ITestUser
{
public int id { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public string FormattedName()
{
return this.FormattedNameDefault();
}
}
Edit*
It is important that the extension method and the method that you are implementing are named differently, otherwise you will likely get a stackoverflow.
it is possible in C# 8.0. You can add a method with default implementation. You will have to change your target framework version to latest to use this feature.
As a newbe C# programmer I was reading through this topic and wondered if the following code example could be of any help (I don't even know if this is the proper way to do it). For me it allows me to code default behavior behind an interface. Note that I used the generic type specifiction to define an (abstract) class.
namespace InterfaceExample
{
public interface IDef
{
void FDef();
}
public interface IImp
{
void FImp();
}
public class AbstractImplementation<T> where T : IImp
{
// This class implements default behavior for interface IDef
public void FAbs(IImp implementation)
{
implementation.FImp();
}
}
public class MyImplementation : AbstractImplementation<MyImplementation>, IImp, IDef
{
public void FDef()
{
FAbs(this);
}
public void FImp()
{
// Called by AbstractImplementation
}
}
class Program
{
static void Main(string[] args)
{
MyImplementation MyInstance = new MyImplementation();
MyInstance.FDef();
}
}
}
C# 11 feature - Now official:
Static virtual members in interfaces
Docs saying:
C# 11 and .NET 7 include static virtual members in interfaces.
This feature enables you to define interfaces that include overloaded
operators or other static members.
Once you've defined interfaces with static members, you can use those interfaces as constraints to create generic types that use operators or other static methods.
So you can:
Define interfaces with static members.
Use interfaces to define classes that implement interfaces with operators defined.
Create generic algorithms that rely on static interface methods.
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/static-virtual-interface-members
Prerequisites
You'll need to set up your machine to run .NET 7, which supports C# 11
I have 2 classes that manage the operation of 2 different brands of net cam, each have exactly the same public members, but very different private members. One or the other of them is docked inside of a Pane class ( which type is decided at run time). The Pane class provides additional display functionality plus control of whichever camera is docked. When an application instantiates the Pane class, and specifies the type of camera is to be docked, I would like to have the Pane instantiate the proper camera class so that it can call on that class.
My issue is illustrated in the last line of this example code... camera doesn't have a .Start() method because camera is of type Object not of one of the two CameraType types.
How do I get 'object camera' to expose at design time the members of the assigned class so that Pane.Start() winds up calling the Start() method of the class assigned in the switch/case block?
Thank you for your time,
Dave
public class CameraType1 //not to be used directly
{
public CameraType1()
{
Stuff specific to this type of camera
}
public void Start()
{
// Stuff specific to starting a stream to this type
}
}
public class CameraType2 //not to be used directly
{
public CameraType2()
{
// Stuff specific to this type of camera
}
public void Start()
{
// Stuff specific to starting a stream to this type
}
}
public class Pane
{
object camera;
public Pane(string CameraTypeToDeploy)
{
switch (CameraTypeToDeploy)
{
case "Type1":
camera = new CameraType1();
break;
case "Type2":
camera = new CameraType2();
break;
}
}
public void Start()
{
camera.Start(); //wrong... camera doesn't have a Start() method
}
}
You need a common base type. You can define an interface that all camera types implement or you can create an abstract base type from which all cameras inherit. Or you can make both. Program against the interface and supply a base class implementing the interface and providing implementations of members commonly used.
public interface ICamera
{
string Name { get; }
void Start();
}
public abstract class CameraBase : ICamera
{
public abstract void Start(); // Needs to be overridden in non abstract classes.
public virtual string Name { get; protected set; } // May be overridden.
}
public class CameraType1 : CameraBase
{
public CameraType1()
{
// Stuff specific to this type of camera
Name = "Type 1";
}
public override void Start()
{
// Stuff specific to starting a stream to this type
}
}
public class CameraType2 : CameraBase
{
public CameraType2()
{
// Stuff specific to this type of camera
Name = "Type 2";
}
public override void Start()
{
// Stuff specific to starting a stream to this type
}
}
public class Pane
{
ICamera camera;
public Pane(string CameraTypeToDeploy)
{
switch (CameraTypeToDeploy) {
case "Type1":
camera = new CameraType1();
break;
case "Type2":
camera = new CameraType2();
break;
}
}
public void Start()
{
camera.Start(); //OK, all cameras have a Start() method
}
}
An interface gives a great flexibility and a high degree of decoupling; however, it does not provide any implementation that can be reused.
A common base class (abstract or not) without interface creates a high degree of coupling between the classes but can provide ready to use implementations of members for all deriving classes.
You can combine the advantages of both, as shown in my example. If a camera should be very different from all the others, you could still decide to let it implement the interface directly without deriving from CameraBase. Of cause you can also have several camera base classes for different groups of resembling cameras (e.g. different camera types from the same company with similar APIs).
UPDATE #1
According to your comment, your camera classes are derived from vendor supplied base types. You can still let them implement an interface.
public class VendorSpecificCamera
{
public string Name { get; }
public bool VendorSpecificStart(int mode, int framesPerSecond)
}
public class CameraType1 : VendorSpecificCamera, ICamera
{
// The 'Name' property is inherited from the vendor specific base class and
// is therefore already implemented in this example.
public bool CameraStarted { get; private set; }
public void Start()
{
CameraStarted = VendorSpecificStart(2, 25);
}
}
In case the vendor type has already members matching the signature of the interface members, you don't have to do anything in your derived class. If not, just supply the missing members.
UPDATE #2
In case a vendor specific camera class should be sealed, you cannot derive your own class from it. You would then create a wrapper class around the vendor class
public class CameraType1 : ICamera
{
private VendorSpecificCamera _camera;
public CameraType1()
{
_camera = new VendorSpecificCamera();
}
public string Name { get { return _camera.Name; } }
public bool CameraStarted { get; private set; }
public void Start()
{
CameraStarted = _camera.VendorSpecificStart(2, 25);
}
}
You can also make the vendor specific camera visible through a read-only property, allowing you to access vendor specific properties.
public VendorSpecificCamera Camera { get { return _camera; } }
You make both implement an interface ICamera:
public interface ICamera
{
void Start();
}
public class Camera1 : ICamera
{
// your existing implementation
}
public class Camera2 : ICamera
{
// your existing implementation
}
public class Pane
{
ICamera camera;
public Pane(string CameraTypeToDeploy)
{
// Your existing code
}
}
public void Start()
{
camera.Start(); //ok, ICamera has a start method
}
}
Interfaces is the simplest way to tell the program that several classes provides the same functionality and can be used interchangably. The other option (abstract classes or simple inheritance) tends to make everything more confusing, but is sometimes an option as well.
Create an interface which contains the .Start() method and have both CameraType1 and CameraType2 implement it. And have the property camera on Pane be of that interface.
public Interface CameraType
{
void Start();
}
public class CameraType1 : ICameraType //not to be used directly
{
public CameraType1()
{
Stuff specific to this type of camera
}
public void Start()
{
// Stuff specific to starting a stream to this type
}
}
public class CameraType2 : ICameraType //not to be used directly
{
public CameraType2()
{
// Stuff specific to this type of camera
}
public void Start()
{
// Stuff specific to starting a stream to this type
}
}
public class Pane
{
ICameraType camera;
public Pane(string CameraTypeToDeploy)
{
switch (CameraTypeToDeploy)
{
case "Type1":
camera = new CameraType1();
break;
case "Type2":
camera = new CameraType2();
break;
}
}
public void Start()
{
camera.Start();
}
}