I have one seemingly simple question about encapsulation in C#.
In one of our school assignments, we're supposed to create a simple two dimensional coordination calculation system, and encapsulate the files correctly, so that we cannot edit the position or length of the points from the Main method.
I created two C# files, namely Line and Point. The file Program.cs was given to us, so we're supposed to work around that, and we're not allowed to change any code in that file. The file we're supposed to encapsulate is the Line.cs or Point.cs files, so that the Main method cannot edit the position of the points from there by writing e.g. p1.X = 0;
.
Below are the files that I've written so far:
Program.cs
using System;
using coordinationSystem;
class Program
{
public static void Main()
{
Point p0 = new Point();
Point p1 = new Point(-10, -10);
Console.WriteLine("Point p0, position = (" + p0.X + ", " + p0.Y + ")");
Console.WriteLine("Point p1, position = (" + p1.X + ", " + p1.Y + ")");
Line theLine = new Line(p0, p1); //This is the correct line.
outdata("Print 1 of the line", theLine);
p1.X = 0; //This is the thing I'm trying to prevent...
outdata("Print 2 of the line", theLine);
Point startposition = theLine.Position();
startposition.Y = 5; //... same with this one
outdata("Print 3 of the line", theLine);
}
private static void outdata(string text, Line theLine)
{
double length = theLine.Length();
Point startPos = theLine.Position();
Console.WriteLine("\n" + text);
Console.WriteLine("==================================");
Console.WriteLine("Length = {0 :f4} units", length);
Console.WriteLine("Position = ({0},{1})", startPos.X, startPos.Y);
Console.WriteLine("----------------------------------");
}
}
Point.cs
namespace coordinationSystem
{
public class Point
{
private int x, y;
public Point() : this(0, 0) { } //Default-constructor.
public Point(int X, int Y) //Constructor.
{
this.X = X;
this.Y = Y;
}
public int X //Property for the X-coordinate.
{
get { return x; }
set
{
x = value;
}
}
public int Y //Property for the Y-coordinate.
{
get { return y; }
set
{
y = value;
}
}
}
}
Line.cs
using System;
namespace coordinationSystem
{
public class Line
{
private Point p0;
private Point p1;
public Line(Point p0, Point p1)
{
this.p0 = p0;
this.p1 = p1;
}
public double Length()
{
double pointLength = Math.Sqrt(Math.Pow(p0.X - p1.X, 2) + Math.Pow(p0.Y - p1.Y, 2));
return pointLength;
}
public Point Position()
{
return p0;
}
}
}
I came to the conclusion that I should probably use get
and set
, but this hasn't worked out for me since the theLine.Position();
in Main is a method (and as I wrote earlier, we're not supposed to edit the Program.cs/Main at all).
So is there any ideas here? Any help will be much appreciated!
EDIT:
This is the assignment text (loosely translated from Swedish):
Consider whether it is possible to sabotage the line if you have access to references to the lines both endpoints. What happens, for example, with the line if you would change the p0 or p1 in the Main method after you have created the line? What happens to the line when you move the starting position in the Main method? Modify the code in the class Line and Point so that the above problems are avoided.
Well, that problem has multiple solutions, here are two:
1-Convert Point to an struct.
Structs are pased by value, not by reference, so when you return p0 on the method it will be a copy, if anyone changes the returned point the original line will remain unchanged.
2-Duplicate the point.
Instead of returning p0 directly, just return new Point(p0.X, p0.Y), it will have the same result as 1
Anyway, try to get your teacher fired, she doesn't knows C#, she knows Java and thus she doesn't understand how properties work as any C# programmer would use properties and not functions to retrieve properties from a higer class like Line.
EDIT: If you use method 2 then also clone the points used on the constructor of Line:
public Line(Point p0, Point p1)
{
this.p0 = new Point(p0.X, p0.Y);
this.p1 = new Point(p1.X, p0.Y);
}