Utilizing C# inheritance correctly - c#

I have written the code below, but i see that for to access the width and the length for the last child which is badRectangle is by overriding everything inhrerited from the Rectangle and shape class, which means i have to duplicate the input and i i had 6 or more levels of inheritance the code would kind of confuse and repeat a lot of things.
This code works correctly but is the correct way of dealing with inheritance in C#.
class Program
{
static void Main(string[] args)
{
badRectangle myRect = new badRectangle(true,"Rectangle",23.0,23);
Console.WriteLine("The Area of your Rectangle = " + myRect.getArea().ToString()
+ "\nAnd " + myRect.getStatus());
Console.ReadLine();
}
public abstract class shape
{
string type;
public abstract double getArea();
public shape(string type)
{
this.type = type;
}
}
public class rectangle : shape
{
double width, length;
public rectangle(string type, double width, double length):base(type)
{
this.width = width;
this.length = length;
}
public override double getArea()
{
return width * length;
}
}
public class badRectangle : rectangle
{
double width, length;
bool badOrNot = false;
public badRectangle(bool badOrNot,string type, double width, double length):base(type,width,length)
{
this.badOrNot = badOrNot;
this.width = width;
this.length = length;
}
public string getStatus()
{
string answer = "No, Rectangle is not bad";
if (badOrNot == true)
{
answer = "Yes, Rectangle is bad";
}
return answer;
}
public override double getArea()
{
return width * length;
}
}
}

This would be the "correct" or conventional way to do this in C#:
public abstract class Shape
{
public string Type { get; private set; }
public abstract double Area { get; }
public Shape(string type)
{
this.Type = type;
}
}
public class Rectangle : Shape
{
public double Length { get; private set; }
public double Width { get; private set; }
public Rectangle(string type, double width, double length)
: base(type)
{
this.Width = width;
this.Length = length;
}
public override double Area { get { return this.Width * this.Length; } }
}
public class BadRectangle : Rectangle
{
public bool BadOrNot { get; private set; } = false;
public BadRectangle(string type, double width, double length, bool badOrNot)
: base(type, width, length)
{
this.BadOrNot = badOrNot;
}
public string Status
{
get
{
string answer = "No, Rectangle is not bad";
if (this.BadOrNot == true)
{
answer = "Yes, Rectangle is bad";
}
return answer;
}
}
}

You don't need to set width and length in the derived classes again, just pass them to the constructor of the base class. If you need to access them in the derived class, make them protected. The getArea() doesn't have to be overridden if it does the same thing.

Related

Cast changing generic type

I have the following classes:
public class Grid<T>
{
public int Width { get; }
public int Height { get; }
public float CellSize { get; }
public Vector2 GridOffset { get; }
public T[,] GridObjects { get; }
public Grid(int width, int height, float cellSize, Vector3 gridOffset, Func<Grid<T>, int, int, T> createGridObjectMethod)
{
this.Width = width;
this.Height = height;
this.CellSize = cellSize;
this.GridOffset = gridOffset;
GridObjects = new T[width, height];
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
GridObjects[x, y] = createGridObjectMethod(this, x, y);
}
}
}
}
public interface IPathNode
{
PathNode GetPathNode();
}
public class PathNode : IPathNode
{
private readonly Grid<IPathNode> grid;
public int X { get; }
public int Y { get; }
public PathNode PreviousNode;
public PathNode(Grid<IPathNode> grid, int x, int y)
{
this.grid = grid;
this.X = x;
this.Y = y;
}
}
Now, I'm trying to create a Grid instance with the following line:
grid = new Grid<PathNode>(10, 10, 1, new Vector3(-5, -5, 0), (g, x, y) =>
{
Grid<IPathNode> test = (Grid<IPathNode>)g;
return new PathNode(g, x, y);
});
The problem is that PathNode asks for a Grid and my grid is made of PathNodes (or any other type that implements that interface).
How can I cast it, or instantiate it?
Tried casting the grid object, but it will fail to compile.
Also adding generics to the PathNode class but I don't like that
I ended up adding a restriction to the PathNode and the interface (and adding generics to it). I had to edit some of the code but it works. Don't really like this option since I only use the generics for it to work but yeah.
public class PathNode<T> : IPathNode<T> where T : IPathNode<T>
public interface IPathNode<T> where T : IPathNode<T>

How would I implement an IInterface class with this code that calculates area of circle, rectangle, triangle?

I need to further my knowledge of IInterface classes used with abstract classes. Whether this stuff is ever used have work requirements to learn a little more about it.
What I think an interface is (this works and calculates area for 3 items, Rectangle, Triangle, Circle using values provided):
static void Main(string[] args)
{
Rectangle r = new Rectangle(4, 8, "Rectangle");
Triangle t = new Triangle(4, 4, "Triangle");
Circle c = new Circle(3, "Circle");
r.DisplayArea();
Console.WriteLine();
t.DisplayArea();
Console.WriteLine();
c.DisplayArea();
Console.ReadKey();
}
Here is my abstract class. It looks like it deals with the name of what is being measured:
namespace DrawShapes
{
abstract class Shape
{
public string name;
public abstract void DisplayArea();
public Shape(string name)
{
this.name = name;
}
}
I'm not positively sure but wouldn't these be in the IInterface class and get set or called somehow? Definitely not an expert at this object oriented stuff.
public int Radius { get; set; }
public int Height { get; set; }
public int Width { get; set; }
Instead, I am hardcoding the parameters into the "function call":
static void Main(string[] args)
{
Rectangle r = new Rectangle(4, 8, "Rectangle");
Triangle t = new Triangle(4, 4, "Triangle");
Circle c = new Circle(3, "Circle");
}
I personally can't think of why or how I would use IInterface.
Just to be complete and maybe help someone who is looking for stuff like this, here are my classes to calculate areas.There are other SO answers to calculate areas, this question is about IInterface and abstract classes:
namespace DrawShapes
{
class Rectangle : Shape
{
public int length;
public int width;
public Rectangle(int length, int width, string name) : base(name)
{
//this.angles = angles;
this.length = length;
this.width = width;
}
public override void DisplayArea()
{
Console.Write(name + "--");
Console.Write(length * width);
}
}
class Triangle : Shape
{
// public int angles;
public int width;
public int height;
public Triangle(int width, int height, string name) : base(name)
{
//this.angles = angles;
this.width = width;
this.height = height;
}
public override void DisplayArea()
{
Console.Write(name + "--");
Console.Write((width * height) / 2);
}
}
class Circle : Shape
{
public int radius;
public Circle(int radius, string name) : base(name)
{
this.radius = radius;
}
public override void DisplayArea()
{
Console.Write(name + "--");
Console.Write(3.22 * radius * radius);
}
}
}

How to pass base parameters from an overloaded constructor into the derived class [duplicate]

This question already has answers here:
Calling the base constructor in C#
(10 answers)
Closed 7 years ago.
Main
static void Main(string[] args)
{
string name = "Me";
int height = 130;
double weight = 65.5;
BMI patient1 = new BMI();
BMI patient2 = new BMI(name,height,weight);
Console.WriteLine(patient2.Get_height.ToString() + Environment.NewLine + patient1.Get_height.ToString() );
Console.ReadLine();
}
Base Class
class BMI
{
//memberVariables
private string newName;
private int newHeight;
private double newWeight;
//default constructor
public BMI(){}
//overloaded constructor
public BMI(string name, int height, double weight)
{
newName = name;
newHeight = height;
newWeight = weight;
}
//poperties
public string Get_Name
{
get { return newName; }
set { newName = value;}
}
public int Get_height
{
get { return newHeight; }
set { newHeight = value; }
}
public double Get_weight
{
get { return newWeight; }
set { newWeight = value; }
}
}
derived class
class Health : BMI
{
private int newSize;
public Health(int Size):base()
{
newSize = Size;
}
}
How do i pass in the base parameters from the overloaded constructor in the BMI base class into the Derived Class?
Any time i try to pass them into the base parameters i get invalid expression error.
Or do i just have to pass them into a Health object in the main with a ?
eg
class Health : BMI
{
private int newSize;
public Health(int Size, string Name, int Height, double Weight)
{
newSize = Size;
base.Get_Name = Name
base.Get_weight = Weight;
base.Get_height = Height;
}
}
Constructors aren't inherited, so yes you need to create a new constructor for the base class, but you can call the base constructor with the proper parameters:
public Health(int size, string name, int height, double weight)
: base(name, height, weight)
{
newSize = size;
}
Like this:
class Health : BMI
{
private int newSize;
public Health(int Size, string Name, int Height, double Weight)
: base(Name, Height, Weight)
{
newSize = Size;
}
}
Why can't you call the base class constructor passing the parameter like
public Health(int Size, string Name, int Height, double Weight)
: base(Name, Height, Weight)
{
newSize = Size;
}

Design pattern for private members access?

Let's use this simple example :
Connect4Board.cs :
public class Connect4Board
{
private Box[,] _boxes = new Box[7, 6];
public void DropPieceAt(int column, bool redPiece)
{
//Safe modifications to box colors.
}
public Box GetBoxAt(int x, int y)
{
return _boxes[x, y];
}
}
Box.cs :
public class Box
{
public bool IsRed { get; private set; }
public bool IsEmpty { get; private set; }
}
I want GetBoxAt() to return a box with read-only properties. However I want my Connect4Board to be able to change boxes colors.
Let's assume that I don't want to use internal modifier at all.
My solution (quite ugly) :
public class Connect4Board
{
private Box.MutableBox[,] _mutableBoxes = new Box.MutableBox[7, 6];
public Connect4Board()
{
for (int y = 0; y < 6; y++)
{
for (int x = 0; x < 7; x++)
{
_mutableBoxes[x, y] = new Box.MutableBox();
}
}
}
public void DropPieceAt(int column, bool isRed)
{
//Safe modifications to box colors.
}
public Box GetBoxAt(int x, int y)
{
return _mutableBoxes[x, y].Box;
}
}
public class Box
{
public bool IsRed { get; private set; }
public bool IsEmpty { get; private set; }
private Box()
{
}
public class MutableBox
{
public Box Box { get; private set; }
public MutableBox()
{
Box = new Box();
}
public void MakeRed() { //I can modify Box here }
public void MakeYellow() { //I can modify Box here }
public void MakeEmpty() { //I can modify Box here }
}
}
Is there a good design pattern to make this more elegant ?
There are a number of strategies you could use.
It's often useful to program to interfaces. The IBox interface below would not allow people to edit the box (without casting it to a Box), but still leaves your code simple.
public class Connect4Board
{
private Box[,] _boxes = new Box[7, 6];
public void DropPieceAt(int column, bool redPiece)
{
//Safe modifications to box colors.
}
public IBox GetBoxAt(int x, int y)
{
return _boxes[x, y];
}
}
public interface IBox
{
bool IsRed { get; }
bool IsEmpty { get; }
}
public class Box : IBox
{
public bool IsRed { get; set; }
public bool IsEmpty { get; set; }
}
Another approach would be to make boxes always immutable (like strings), and instead of modifying the states of your boxes, you just modify which box is in which location in your array:
public class Connect4Board
{
private Box[,] _boxes = new Box[7, 6];
public Connect4Board()
{
for(int i = 0; i<7; i++)
{
for(int j = 0; j<6; j++)
{
// Notice how you're not changing a color, but assigning the location
_boxes[i,j] = Box.Empty;
}
}
}
public void DropPieceAt(int column, bool redPiece)
{
// Modifications to the top empty location in the given column.
}
public Box GetBoxAt(int x, int y)
{
return _boxes[x, y];
}
}
public class Box
{
public bool IsRed { get; private set; }
public bool IsBlack { get; private set; }
public bool IsEmpty { get; private set; }
private Box() {}
public static readonly Box Red = new Box{IsRed = true};
public static readonly Box Black = new Box{IsBlack = true};
public static readonly Box Empty = new Box{IsEmpty = true};
}
WOuld this work for you?
Make Box Immutable, with static factory, and add static properties that return new boxes with various colors
public class Box
{
private Box() {}
private Box(Color color) { Color = color; }
public static Box Make(Color color) { return new Box(color); }
public static Box RedBox { get { return new Box(Color.Red); } }
public static Box GreenBox { get { return new Box(Color.Green); } }
public static Box BlueBox { get { return new Box(Color.Blue); } }
// ... etc.
}
Solution 1
You could create a wrapper around Box which is immutable. Connect4Board would use the MutableBox class internally but would expose ImmutableBox to consumers.
public interface IBox
{
bool IsRed { get; }
bool IsEmpty { get; }
}
public class MutableBox : IBox
{
public bool IsRed { get; set; }
public bool IsEmpty {get; set; }
public IBox MakeImmutable()
{
return new ImmutableBox(this);
}
}
public class ImmutableBox : IBox
{
private IBox innerBox;
public ImmutableBox(IBox innerBox) { this.innerBox = innerBox; }
public bool IsRed { get { return innerBox.IsRed; } }
public bool IsEmpty { get { return innerBox.IsEmpty; } }
}
public class Connect4Board
{
private MutableBox[,] boxes = new MutableBox[7, 6];
public void DropPieceAt(int column, bool redPiece)
{
// perform modifications
}
public IBox GetBoxAt(int x, int y)
{
return boxes[x,y].MakeImmutable();
}
}
Solution 2
You could maybe use explicit interface implementation to achieve this?
Create an interface IMutableBox.
public interface IMutableBox
{
void SetIsRed(bool isRed);
void SetIsEmpty(bool isEmpty);
}
public class Box : IMutableBox
{
private bool isRed;
private bool isEmpty;
public bool IsRed { get { return isRed; } }
public bool IsEmpty { get { return isEmpty; } }
void IMutableBox.SetIsRed(bool isRed)
{
this.isRed = isRed;
}
void IMutableBox.SetIsEmpty(bool isEmpty)
{
this.isEmpty = isEmpty;
}
}
Now, in order to mutate Box, you would need to cast it to an IMutableBox.
var box = new Box();
var mutableBox = box as IMutableBox;
mutableBox.SetEmpty(true);
You can make a ReadOnlyBox that can be a facade for your Box much like a ReadOnlyCollection.
[Flags]
public enum BoxState
{
Empty = 0,
Red = 1 << 0,
Black = 1 << 1
}
[Flags]
public enum BoardColor
{
Red = 1 << 0,
Black = 1 << 1
}
public interface IBox
{
BoxState State { get; }
}
public class Box : IBox
{
public BoxState State { get; set; }
}
public class ReadOnlyBox : IBox
{
private readonly IBox _box;
public ReadOnlyBox(IBox box)
{
_box = box;
}
public BoxState State { get { return _box.State; } }
}
public class Connect4Board
{
private const int _boardWidth = 7;
private const int _boardHeight = 6;
private Box[,] _boxes = new Box[_boardWidth, _boardHeight];
public void DropPieceAt(int column, BoardColor color)
{
for(int height = 0; height < _boardHeight; height++)
{
if(_boxes[column, height].State != BoxState.Empty) continue;
_boxes[column, height].State = (BoxState)color;
break;
}
}
public IBox GetBoxAt(int x, int y)
{
return new ReadOnlyBox(_boxes[x, y]);
}
}

C#: Pass derived class as parameter

I have a base class that does calculations on image sizes. I'm deriving a class from that and have predefined image sizes that will be used in my code. While what I have works, I have a strong feeling that I'm not doing it properly.
Ideally, I'd like to just pass DerviedClass.PreviewSize as the parameter to GetWidth without having to create an instance of it.
class Program
{
static void Main(string[] args)
{
ProfilePics d = new ProfilePics();
Guid UserId = Guid.NewGuid();
ProfilePics.Preview PreviewSize = new ProfilePics.Preview();
d.Save(UserId, PreviewSize);
}
}
class ProfilePicsBase
{
public interface ISize
{
int Width { get; }
int Height { get; }
}
public void Save(Guid UserId, ISize Size)
{
string PicPath = GetTempPath(UserId);
Media.ResizeImage(PicPath, Size.Width, Size.Height);
}
}
class ProfilePics : ProfilePicsBase
{
public class Preview : ISize
{
public int Width { get { return 200; } }
public int Height { get { return 160; } }
}
}
It seems to me that you want a more flexible implementation of ISize - having an implementation which always returns the same value seems fairly pointless. On the other hand, I can see that you want an easy way of getting the size that you always use for a preview. I would do it like this:
// Immutable implementation of ISize
public class FixedSize : ISize
{
public static readonly FixedSize Preview = new FixedSize(200, 160);
private readonly int width;
private readonly int height;
public int Width { get { return width; } }
public int Height { get { return height; } }
public FixedSize(int width, int height)
{
this.width = width;
this.height = height;
}
}
You could then write:
ProfilePics d = new ProfilePics();
Guid userId = Guid.NewGuid();
d.Save(userId, FixedSize.Preview);
This would reuse the same instance of FixedSize whenever you called it.
There are a few ways that you could do this, depending on your needs. I would look at doing a different interface, setup. Something like this.
public interface ISizedPics
{
int Width {get; }
int Height {get; }
void Save(Guid userId)
}
public class ProfilePics, iSizedPics
{
public int Width { get { return 200; } }
public int Height { get { return 160; } }
public void Save(Guid UserId)
{
//Do your save here
}
}
Then, with this done, you could actually work with it like this.
ISizedPics picInstance = new ProfilePics;
Guid myId = Guid.NewGuid();
picInstance.Save(myId);
This is just one way of doing it, I like this way, as you can easily create a factory class around this that helps you declare the instances as needed.

Categories