Reputation: 1457
Can some one tell me how to define the class Student such that the last test case is satisfied. I could not understand how the method implementation of last function GetId().
public const int basicId = 12345;
public const int studentId = 88888;
public const string sampleName = "User Name";
[TestMethod]
public void StudentIsInitializedCorrectly()
{
User student = new Student(sampleName, basicId, studentId);
Assert.AreEqual(sampleName, student.GetName());
Assert.AreEqual(basicId, student.GetId());
Assert.AreEqual(studentId, ((Student)student).GetId());
}
Thanks
Upvotes: 0
Views: 185
Reputation: 70701
I understand from the comments that you are working through some test-driven-development (TDD) exercises, and that you are having trouble understanding this example. So with that in mind, here's how I look at it:
Student
, it is being assigned to a variable that has the type User
. There are different ways that this could work, but the most obvious explanation is that User
is the base class, and that Student
inherits User
.student
variable directly. Since the type of this variable is User
, those methods must exist in the User
class. Again there are multiple ways that this could actually work, but the simplest is to assume that the values those methods need to return are in fact stored in the User
class.Those two points lead us to a User
class that looks something like this:
class User
{
private readonly string _name;
private readonly int _id;
public User(string name, int id)
{
_name = name;
_id = id;
}
public string GetName() { return _name; }
public int GetId() { return _id; }
}
The above ensures that when we view the object instance through a variable having the type User
, that we can still call the GetName()
and GetId()
methods, and get back the values we expect.
Now we come to the third and final test in the method. Note that this test casts the student
variable to the class Student
before calling the method. Note also that this method is expected to return the value in studentId
and not the value in basicId
, which is the value that the base class's GetId()
method is supposed to return.
So we have the same method name, used on the same object instance, but which is supposed to behave differently depending on the compile-time type of the object (aka "static type"). This is as opposed to the run-time type, which is the actual type of the object.
Given that, we have to declare a new GetId()
method in the Student
class, and of course provide a way for it to return the different ID value that was used during the initialization of the object:
class Student : User
{
private readonly int _id;
public Student(string name, int basicId, int studentId)
: base(name, basicId)
{
_id = studentId;
}
public new int GetId() { return _id; }
}
The one wrinkle is that given that we already know the User
class has a method with this exact same name, you will be hiding that class's method with your new GetId()
method. Thus, the new
keyword is required to avoid any compile-time warnings.
My personal preference is to avoid method hiding always. It is pretty much always the wrong design choice, and should be used only when forced into it by some outside requirement.
(Note that the fields in the above classes are marked readonly
. There's nothing in the test that requires this to be the case, but there's also nothing in the test that prevents it. My preference is to make fields readonly
unless they can't be, hence the use of readonly
here).
Upvotes: 3