My class Ellipse should inherit from my class Shape but I get this error message:
Error 1 'ConsoleApplication3.Ellipse' does not implement inherited abstract member 'ConsoleApplication3.Shape.Perimeter.get'
I also get the error message that I'm hiding Area, a property in Ellipse.
Can anyone help me please?
My shape class looks like this:
public abstract class Shape
{
//Protected constructor
protected Shape(double length, double width)
{
_length = length;
_width = width;
}
private double _length;
private double _width;
public abstract double Area
{
get;
}
And my ellipse class is:
class Ellipse : Shape
{
//Constructor
public Ellipse(double length, double width)
:base(length, width)
{
}
//Egenskaper
public override double Area
{
get
{
return Math.PI * Length * Width;
}
}
}
You need to use the override modifier on the Area and Perimeter properties in your Ellipse class, e.g.
public override double Area { get; }
public override double Perimeter { get; }
A tip for you in Visual Studio, put the cursor inside the text 'Shape' (in your ellipse class) and press Ctrl + .. This should add stubs for members you haven't implemented
May be this is what you after as you have not declared Length , Width any where in your Ellipse class so you might be getting compilation errors, to compile this you need enhance visibility of _length and _width properties of your base class Shape.
public abstract class Shape
{
//Protected konstruktor
protected Shape(double length, double width)
{
_length = length;
_width = width;
}
// have these variables protected since you instantiate you child through the parent class.
protected double _length;
protected double _width;
public abstract double Area
{
get;
}
}
class Ellipse : Shape
{
//Konstruktor
public Ellipse(double length, double width)
: base(length, width)
{
}
//Egenskaper
public override double Area
{
get
{
// use the variable inherited since you only call the base class constructor.
return Math.PI * _length * _width;
}
}
}
Related
It makes sense that I should not call an overridden function from a base constructor, since the derived class is not yet constructed.
But I want to use this design pattern, where each derived class provides methods for calculating the properties of the base class since the properties should be immutable and assigned at the constructor.
Shape.cs
public abstract class Shape
{
protected Shape()
{
Area = 0f;
Center = Vector2.Zero;
const int n = 36;
float du = 1/(float)n, dv = 1/(float)n;
for (int i = 0; i < n; i++)
{
float u = (i+0.5f)*du;
for (int j = 0; j < n; j++)
{
float v = (i+0.5f)*dv;
float f = GetAreaElement(u, v);
// Warning: Remove this call from a constructor to the overridable 'GetAreaElement' method.
Area += f*du*dv;
Center += GetPosition(u, v)*f*du*dv;
// Warning: Remove this call from a constructor to the overridable 'GetPosition' method.
}
}
Center /= Area;
}
public abstract Vector2 GetPosition(float u, float v);
protected abstract float GetAreaElement(float u, float v);
public float Area { get; }
public Vector2 Center { get; }
}
public class Circle : Shape
{
public Circle(float radius)
{
Radius=radius;
}
public float Radius { get; }
public override Vector2 GetPosition(float u, float v)
{
float r = u*Radius, θ = (float)(2*Math.PI)*v;
return new Vector2(
r*(float)Math.Cos(θ),
r*(float)Math.Sin(θ));
}
protected override float GetAreaElement(float u, float v)
{
return u*Radius;
}
}
public class Rectangle : Shape
{
public Rectangle(float side1, float side2)
{
Side1=side1;
Side2=side2;
}
public float Side1 { get; }
public float Side2 { get; }
public override Vector2 GetPosition(float u, float v)
{
return new Vector2((u-0.5f)*Side1, (v-0.5f)*Side2);
}
protected override float GetAreaElement(float u, float v)
{
return Side1*Side2;
}
}
So what is the solution here? I want to use the base constructor to define the properties, and the calculation depends on the implementation of the derived class.
Workaround 1 - Future calculator
A workaround would be to provide a protected function that calculates the properties, each to be called from each constructor of the derived class, but there is no enforcement here. If one class forgets to call the calculator function the whole thing falls apart. And the properties are now private set which is not immutable really.
public abstract class Shape
{
protected void Calculate()
{
...
float f = GetAreaElement(u, v);
...
Center += GetPosition(u, v)*f*du*dv;
...
}
public abstract Vector2 GetPosition(float u, float v);
protected abstract float GetAreaElement(float u, float v);
public float Area { get; private set; }
public Vector2 Center { get; private set; }
}
public class Circle : Shape
{
public Circle(float radius)
{
Radius=radius;
base.Calculate();
}
public float Radius { get; }
public override Vector2 GetPosition(float u, float v)
{
...
}
protected override float GetAreaElement(float u, float v)
{
...
}
}
Workaround 2 - Function delegates
Another workaround would be to supply the delegates to the required function implementations as arguments to the base class constructor.
public delegate float AreaFactor(float u, float v);
public delegate Vector2 PositionFunc(float u, float v);
public abstract class Shape
{
protected Shape(AreaFactor a, PositionFunc p)
{
this.GetAreaElement = a;
this.GetPosition = p;
...
float f = a(u, v);
this.Center += p(u, v)*f*du*dv;
...
}
public float Area { get; }
public Vector2 Center { get; }
public AreaFactor GetAreaElement { get; }
public PositionFunc GetPosition { get; }
}
public class Circle : Shape
{
public Circle(float radius)
: base(
(u, v) => u*radius,
(u,v)=>
{
float r = u*radius, θ = (float)(2*Math.PI)*v;
return new Vector2(
r*(float)Math.Cos(θ),
r*(float)Math.Sin(θ));
})
{
Radius=radius;
}
public float Radius { get; }
}
This seems a bit clunky to me, and I am not sure I like the function delegate properties, instead of overridden methods.
Question/Challege
Can [SO] provide some other ways of achieving the above-stated goals
Base properties are immutable
Base properties are calculated at the constructor based on the implementation details of the derived classes.
Each derived class holds its own immutable properties used to describe the derived class.
One option is to, instead of calculating the Area and Center in the constructor, lazily calculate them in the property getter. It will require a backing field to know if the property has been calculated or not, but it will get rid of the warning.
It also seems odd to me that you don't pass the center to the Shape constructor, but I don't fully understand the design you're using.
My preference is to go with Option 2 - passing to the base constructor the methods to generate the derived properties. It does satisfy all your requirements. If aesthetics is a concern, perhaps using a Func might make the code easier to read. The key is that the Func's are static methods, which should not be a problem since they calculate immutable properties of the object.
void Main()
{
var square = new Square(5);
}
public abstract class Shape
{
protected Shape(Func<int> areaFunc)
{
Area = areaFunc();
}
public int Area { get; }
}
public class Square : Shape
{
public Square(int side): base( () => CalcArea(side) )
{
Side = side;
}
static int CalcArea(int side) => side * side;
public int Side { get; }
}
I'm learning inheritance and I understand the code below.
namespace InheritanceApplication {
class Shape {
public void setWidth(int w) {
width = w;
}
public void setHeight(int h) {
height = h;
}
protected int width;
protected int height;
}
// Base class PaintCost
public interface PaintCost {
int getCost(int area);
}
// Derived class
class Rectangle : Shape, PaintCost {
public int getArea() {
return (width * height);
}
public int getCost(int area) {
return area * 70;
}
}
class RectangleTester {
static void Main(string[] args) {
Rectangle Rect = new Rectangle();
int area;
Rect.setWidth(5);
Rect.setHeight(7);
area = Rect.getArea();
// Print the area of the object.
Console.WriteLine("Total area: {0}", Rect.getArea());
Console.WriteLine("Total paint cost: ${0}" , Rect.getCost(area));
Console.ReadKey();
}
}
}
However, why have they created the set height and set width functions. Would it not be better practice to simply just do this:
public int width {get;set;}
public int height {get;set;}
and then in the main class just do something like below:
rect.width = 5;
rect.height = 7;
Many thanks,
Amir
I'm sure others will provide different points, but here are my main 2 reasons for using gets/sets. If these don't apply for a given property, chances are I won't use getters/setters.
1 - Debugging
It makes it significantly easier to debug data propagation (how data gets passed around) if you can debug a setter that you're concerned about. You can easily throw in a Debug.Print call and debug the value being set if you're concerned it's being passed the wrong value. Or you could place break points and actually debug through the stack trace. For example:
class Shape {
public void setWidth(int w) {
if(w < 0)
Debug.Print("width is less than 0!");
width = w;
}
public void setHeight(int h) {
height = h;
}
protected int width;
protected int height;
}
2 - Value Change Actions
There may be better ways to achieve this, but I like being able to add simple logic to setters to ensure that any logic that needs to run when a value changes does so. For instance I may use the following:
public void SetWindowHeight(int newHeight)
{
if(WindowHeight == newHeight)
return;
WindowHeight = newHeight;
UpdateWindowDisplay();
}
public int GetWindowHeight()
{
return WindowHeight;
}
private int WindowHeight;
public void UpdateWindowDisplay()
{
Window.UpdateHeight(WindowHeight);
// Other window display logic
}
Although personally I prefer to use property gets/sets, but that's just my preference.
public int WindowHeight
{
get
{
return windowHeight;
}
set
{
if(windowHeight == value)
return;
windowHeight = value;
UpdateWindowDisplay();
}
}
private int windowHeight;
public void UpdateWindowDisplay()
{
Window.UpdateHeight(WindowHeight);
// Other window display logic
}
A friend recently had a telephone interview and he was asked a technical question:
Q) If I wanted to calculate the surface area of some 2D shapes then what "Bucket" would I use. He had 20 minutes to write some code and the interviewer called him back. He sent the code via email and the code was not discussed for the remainder of the interview (there were no other technical questions). He sent me the code:
Windows Forms app
namespace ShapesApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += form_load;
}
public void form_load (Object o, EventArgs e)
{
List<Shape> listShape = new List<Shape>();
Shapes.Circle circle = new Shapes.Circle();
Shapes.Rectangle rectangle = new Shapes.Rectangle();
Shapes.Square square = new Shapes.Square();
Shapes.Triangle triangle = new Shapes.Triangle();
listShape.Add(rectangle);
listShape.Add(square);
listShape.Add(triangle);
foreach (Shape shape in listShape)
{
double a = 10;
double b = 10;
double surfaceArea = shape.CalculateSurfaceArea(a,b);
Console.WriteLine("The surface area of a " + shape.GetType() + " is: " + surfaceArea);
}
}
}
}
Shapes - Class Library
namespace Shapes
{
public abstract class Shape
{
abstract public double CalculateSurfaceArea(double Double1, double Double2);
}
public class Circle : Shape
{
public override double CalculateSurfaceArea(double pi, double radius)
{
return (pi * radius) * (pi * radius);
}
}
public class Triangle : Shape
{
public override double CalculateSurfaceArea(double Base, double Height)
{
return (Base*Height)/2;
}
}
public class Rectangle : Shape
{
public override double CalculateSurfaceArea(double Length, double Width)
{
return Length * Width;
}
}
}
The interviewer has said that he "struggled" with the test. What is wrong with the code?
Calculating area is the behavior and every shape has his own formula for calculating it. Because calculating area can involve different amount of variables and constants method will not take any parameter and variables will be concern of class which implement interface .
So I think method of calculating area can be abstracted as interface:
public interface ICalculatingArea
{
double CalculateArea();
}
Then every shape will implement it on its own manner.
public class Rectangle:ICalculatingArea
{
public double Width {get; set;}
public double Length {get; set;}
public double CalculateArea()
{
return Length * Width;
}
}
In the main program it is enough to cast shape classes to the interface type and use CalculateArea method
I have this bit of code and it will demonstrate a Liskov substitution, but I'm confused what the base keyword is doing with 2 arguments. Can someone explain?
class Rectangle
{
public Rectangle(int width, int height)
{
Width = width;
Height = height;
}
public virtual int Height {get;set;}
public virtual int Width {get;set;}
public int Area
{
get { return Height*Width }
}
And now for the square class that inherits the base class with 2 arguments. I was also curious why this next Method Square(int) can use a method in the base class with a different name
private class Square : Rectangle
{
public Square(int size) : base(size, size) {} ///here is my confusion
public override int Width
{
get {return base.Width}
set { base.Width = value; base.Height = value}
}
public override int Height
{ /// same thing as Width }
}
base(size, size) calls the parent constructor ( Rectangle's in this case ), this constructor takes 2 arguments, that's why size is specified twice.
Because a square must have the same height and width the size parameter can be used for both width and height
I currently have a class called:
public class HeatmapComponent : GH_Component
I also have another class called:
public class HeatMap
Inside the Heatmap class I have two instance variables declared as:
public int _width;
public int _height;
I would like to be able to access and set the _width and _height variables from the HeatmapComponent class. I know this is a scope issue, but, I am a bit confused as to what needs to be done.
In my HeatmapComponent class, this was what I had in mind:
this._width = width; // width is declared somewhere in this class
this._height = height; // height is same as above
I apologize beforehand if this is a stupid question. Please let me know if I am missing code snippets. I'll be happy to provide.
You want to set the values of those two fields? They are readonly. You can do that only in the constructor.
public class HeatMap
{
private readonly int _width;
private readonly int _height;
public HeatMap(int wid, int hei)
{
_width = wid;
_height = hei;
}
}
And, as it is with passing things through constructor's params, you can use/provide them only when building a new instance. That's why they are called constructor and readonly fields:
public class HeatmapComponent
{
private int widthOfMap;
private int heightOfMap;
void createMapAndDoSomething()
{
var hmap = new HeatMap(widthOfMap, heightOfMap);
hmap.thing();
}
}
If you don't want to create a new HeatMap, and if you want to be able to set the width/height from some 'external' place at any point in time, then:
they cannot be readonly
some public way of changing them must exist
For example:
public class HeatMap
{
private int _width;
private int _height;
public void SetSize(int wid, int hei)
{
_width = wid;
_height = hei;
}
}
public class HeatmapComponent
{
private int widthOfMap;
private int heightOfMap;
private HeatMap oldMap;
void changeTheSizes()
{
oldMap.SetSize(widthOfMap, heightOfMap);
}
}
Or sometimes even better, use properties:
public class HeatMap
{
private int _width;
private int _height;
public int Width { set { _width = value; } }
public int Height { set { _height = value; } }
}
public class HeatmapComponent
{
private int widthOfMap;
private int heightOfMap;
private HeatMap oldMap;
void changeTheSizes()
{
oldMap.Width = widthOfMap;
oldMap.Height = heightOfMap;
}
}
Before I answer your question, you have one major, major issue: readonly. That means that the value of the variable cannot be changed once the object is created. By anyone. Period.
Now, you have a couple ways to do this. The first is to use properties like Snorre said. In effect, you'd get this:
public class HeatMap
{
public int Width { get; set; }
public int Height { get; set; }
}
public class HeatMapComponent
{
private HeatMap myHeatMap; // Must have a reference to the object you want to change!
public void SomeMethod()
{
myHeatMap.Width = 10;
}
}
Now, the obvious downside here is that ANYONE can change the properties of HeatMap. If for some reason you really, really want to make HeatMap's width and height editable only by the HeatMapComponent, you can make HeatMapComponent an inner class, like this:
public class HeatMap
{
private int width;
private int height;
public class HeatMapComponent
{
public HeatMap myHeatMap;
public void SomeMethod()
{
myHeatMap.width = 10;
}
}
}
however, I would strongly advise you to rethink what you're trying to do. Public inner classes are actually quite rare, in my experience, as they can violate OOP principles easily. A different application design may suit you better.
Couple of things:
readonly keyword makes anything settable only in the constructor. Example:
class XYZ
{
private readonly int x;
public XYZ()
{
x = 10; //works
}
public void SomeMethod()
{
x = 100; //does not work since it is readonly
}
}
Then there's the various access modifiers: private is only accessible in the class itself, protected is accessible in inherited classes and public is accessible anywhere. Internal is accessible within the same assembly.
public class HeatMapComponent
{
HeatMap _map;
public HeatMapComponent()
{
_map = new HeatMap();
}
public void SomeMethod()
{
_map.Width = 10; //should work if Width is public and not readonly and if _map was initialized already, ie not null
}
}
This sounds like a homework question, and the problem is you are not understanding the lesson.
Here's a way to create your HeatMap class. It contains an overload so you can either set the Width and Height in the constructor or via a Set method:
public class HeatMap {
public HeatMap() {
Width = 0;
Height = 0;
}
public HeatMap(int width, int height) {
Width = width;
Height = height;
}
public void Set(int width, int height) {
Width = width;
Height = height;
}
public int Width { get; private set; }
public int Height { get; private set; }
}
To use this in your HeatmapComponent class, you only need to create an instance of your HeatMap. Here are two ways of doing that:
public HeatmapComponent() {
}
public void Test1(int width, int height) {
var hm = new HeatMap(width, height);
Console.WriteLine("Width: {0}, Height: {1}", hm.Width, hm.Height);
}
public static void Test2(int width, int height) {
var hm = new HeatMap();
hm.Set(width, height);
Console.WriteLine("Width: {0}, Height: {1}", hm.Width, hm.Height);
}
Be sure you understand what is going on, though.