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
Related
I have this code and I am trying to calculate the area and circumference of the circle. I have tried debugging and I can see that the radius was passed but the area and circumference is not, it's always 0.
using System;
class Circle{
double radius;
double area;
double circumference;
public double Radius{set{radius = value;}}
public double Area{set{area=value;}}
public double Circumference{set{circumference=value;}}
public Circle(double radius){
this.radius = radius;
area=0;
circumference=0;
}
void CalculateArea(){
area=Math.PI*Math.Pow(radius,2);
}
void CalculateCircumference(){
circumference = 2*Math.PI*radius;
}
public void DisplayArea(){
System.Console.WriteLine("Area is {0}",area);
}
public void DisplayCircumference(){
System.Console.WriteLine("Circumference is {0}",circumference);
}
}
class TestCircle{
public static void Main(string[] args)
{
System.Console.WriteLine("Enter radius: ");
double radius=Convert.ToDouble(Console.ReadLine());
Circle theCircle = new Circle(radius);
theCircle.DisplayArea();
theCircle.DisplayCircumference();
}
}
this is the output
Enter radius:
3
Area is 0
Circumference is 0
You have a very strange design: set only Radius (once set I can't read it), editable (both get and set) Area: one
can easily assign -1.0 to it...
Let's redesign it; we have Circle class with three properties only:
class Circle{
// Radius, the man property we can
// - read it (get)
// - assign it, but let it be just once (so set is private)
public double Radius {get; private set;}
// Area, which we can just read (get, no set)
public double Area => Math.PI * Radius * Radius;
// Circumference, which we can just read (get, no set)
public double Circumference => 2 * Math.PI * Radius;
public Circle(double radius) {
Radius = radius;
}
public void DisplayArea(){
System.Console.WriteLine($"Area is {Area}");
}
public void DisplayCircumference(){
System.Console.WriteLine($"Circumference is {Circumference}");
}
}
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; }
}
There are three errors while compiling the code.
1.Using the generic type List requires 1 argument.
2.Using the generic type List requires 1 argument.
3. foreach statement cannot operate on variables of type because List does not contain a public definition for 'GetEnumerator'
The program of Polymorphism example is below.
namespace PolymorExample
{
abstract class Shape
{
public abstract void area();
}
class Rectangle : Shape
{
private double length;
private double width;
public Rectangle(double length, double width)
{
this.length = length;
this.width = width;
}
public override void area()
{
Console.WriteLine("Rectangel Area: {0}", length * width);
}
}
class Triangle : Shape
{
private double baseline;
private double height;
public Triangle(double baseline, double height)
{
this.baseline = baseline;
this.height = height;
}
public override void area()
{
Console.WriteLine("Triangel Area: {0}", baseline * height / 2.0);
}
}
class Circle : Shape
{
const double PI = 3.14;
private double radius;
public Circle(double radius)
{
this.radius = radius;
}
public override void area()
{
Console.WriteLine("Circle Area: {0}", radius * radius * PI);
}
}
public class TestShape
{
static void Main()
{
List shapes = new List();
Shape shape1 = new Rectangle(10, 10);
shapes.Add(shape1);
shapes.Add(new Circle(10));
shapes.Add(new Triangle(10, 10));
shapes.Add(new Circle(20));
foreach (Shape s in shapes)
{
s.area();
}
Console.Read();
}
}
}
If you take a look at the documentation for the List<T> class, you'll notice that List is a generic type (hence the <T>), and generic types require a parameter (or more) that specifies the type(s) of object it will use/contain. You must specify some type, even if it's just object.
In your case, you have a list of Shape objects, so your initialization code can be modified (and simplified by using collection initializer syntax) to specify that type:
var shapes = new List<Shape>
{
new Rectangle(10, 10),
new Circle(10),
new Triangle(10, 10),
new Circle(20)
};
List<Shape> shapes = new List<Shape>();
you need the shape type in your list declaration so it knows what its a list of
By way of an intro, I'm creating a basic Quadtree engine for personal learning purposes. I'm wanting this engine to have the capability of working with many different types of shapes (at the moment I'm going with circles and squares) that will all move around in a window and perform some sort of action when collision occurs.
Here are my shape objects as I have them so far:
public class QShape {
public int x { get; set; }
public int y { get; set; }
public string colour { get; set; }
}
public class QCircle : QShape {
public int radius;
public QCircle(int theRadius, int theX, int theY, string theColour) {
this.radius = theRadius;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
public class QSquare : QShape {
public int sideLength;
public QSquare(int theSideLength, int theX, int theY, string theColour) {
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
Now my question is, how do I create a generic list (List<T> QObjectList = new List<T>();) in C# so I can have one list containing all these various shapes that may have different properties (e.g., QCircle has the "radius" property while QSquare has the "sideLength" property)? An example of implementation would be helpful as well.
I just know that there is a stupidly obvious answer to this question but I'd appreciate any help anyway. I'm trying to get back into C#; it has obviously been a while...
You need to use downcasting
Store the objects in a list with the base class
List<QShape> shapes = new List<QShape>
You can then upcast the object safely if you know what it is e.g.
if(shapes[0] is QSquare)
{
QSquare square = (QSquare)shapes[0]
}
You can also implicitly downcast objects
QSquare square = new Square(5,0,0,"Blue");
QShape shape = square
For more information read the Upcasting and Downcasting sections here
You should implement an Interface. For example
public interface IHasLength
{
int Length;
}
Then in the implementation you can do
public class QSquare : QShape, IHasLength {
public int sideLength;
public QSquare(int theSideLength, int theX, int theY, string theColour) {
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
public int Length { get { return sideLength; } }
}
public class QCircle : QShape, IHasLength {
public int radius;
public QSquare(int theSideLength, int theX, int theY, string theColour) {
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
public int Length { get { return radius; } }
}
FInally, in your list:
List<IHasLength> shapesWithSomeLength = new List<IHasLength>();
Now your list can hold ANYTHING that implements IHasLength whether it's a QCircle, QShape, or even a QDuck if you want as long as it implements IHasLength.
Is this what you want?
public class QShape
{
protected QShape() { }
public int x { get; set; }
public int y { get; set; }
public string colour { get; set; }
}
public class QCircle : QShape
{
public int radius;
public QCircle(int theRadius, int theX, int theY, string theColour)
{
this.radius = theRadius;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
public class QSquare : QShape
{
public int sideLength;
public QSquare(int theSideLength, int theX, int theY, string theColour)
{
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
class Program
{
static void Main(string[] args)
{
List<QShape> list = new List<QShape>();
list.Add(new QCircle(100, 50, 50, "Red"));
list.Add(new QCircle(100, 400, 400, "Red"));
list.Add(new QSquare(50, 300, 100, "Blue"));
foreach (var item in list.OfType<QCircle>())
{
item.radius += 10;
}
foreach (var item in list.OfType<QSquare>())
{
item.sideLength += 10;
}
}
}
You could store them in a List<QShape> but this would mean that you could not access type-specific properties.
Generally, you might approach this by providing a common interface in your base class, and overriding behaviour in subclasses. In this way, a common interface can hide a diverse bunch of behaviours. For instance a Grow method could hide the complexities of growing items of different shape and could be called without explicit knowlege of the shape upon which it is operating.
public abstract class QShape {
public abstract void Grow(int amt);
}
public class QSquare : QShape {
private int sideLength;
public override void Grow(int amt)
{
sideLength+=amt;
}
}
public class QCircle : QShape {
private int radius;
public override void Grow(int amt)
{
radius+=amt;
}
}
I feel like i'm missing something but...
List<QCircle> circleObjects = new List<QCircle>();
and
List<QSquare> squareObjects = new List<QSquare>();
will work perfectly well.
EDIT:
Ah, I didn't understand what was being asked.
Yes, as your QCircle and QSquare classes inherit from QShape, you can just do.
List<QShape> shapes= new List<QShape>();
It's worth noting that if you want to access the radius property of all the QCircle's in that list, then you are going to have to filter the list based on type.
You can use Ian Mercer's comment List<QShape>
And here's how you would fill it:
List<QShape> shapes = new List<QShape>();
QCircle circle = new QCircle();
shapes.Add(circle);
To unbox it:
QCircle circle = (QCircle) shapes[0];
If you need to call a method off the base class, no need to unbox, just use it.
Storing
You're already on the right track with your class definitions. What you have to do is make a List of the superclass (in this case, QShape), which will be able to hold all of your shapes.
Here's an example of how you would make it:
List<QShape> objects = new List<QShape>();
objects.add(new QCircle(...));
objects.add(new QSquare(...));
Accessing
The problem here is differentiating what is what once everything is in the list. That's done with the getType() and typeof() methods of C#. (Jon Skeet has an excellent answer about how to do this). Basically, it looks like this:
if(objects.get(some_position).getType() == typeof(QCircle))
QCircle circle = objects.get(some_position);
else if(/* like above with QSquare */)
QSquare square = objects.get(some_position);
After you do this, you can resume using your objects like normal. But if you try accessing them from the list, you can only use the methods and variables that QShape has, as every object put in the list will be cast to it.
public Class abstract Base<T>
{
public abstract List<T>GetList();
}
then do this
public class className:Base<ObjectName>
{
public override List<T>GetList()
{
//do work here
}
}
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;
}
}
}