ADT Temperature Exercise

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 14

Abstract Data Type

An abstract data type is a user defined type that hides the internal workings and provides a set of
methods that can be used to manipulate instance variables of that type.

“Description: An ADT is a formally specified set of values and associated operations,


independent from any particular implementation. ADTs are one of the foundations of OO,
because they formalize the notion of ‘information hiding’ or ‘encapsulation’, which hides the
implementation of an ADT (i.e., a class) behind its interface.”

Ref: ADT in Web and XML Glossary, http://dret.net/glossary/adt (last accessed 9/2009)

In this exercise you are going to define and implement a Temperature ADT using the class construct
in C#.

Initial UML Class Diagram Name of Class

Temperature Private Attributes (instance variables)


double temp Used to hold the state of objects defined
from the class
void setTemp(double t,char s)
double getKelvin()
double getCelsius() Public methods
string getstrKelvin()
Define the permitted behaviour of
objects defined from the class

The class will define one private attribute (instance variable) called temp. The temp variable will be
defined as a double and will store the degrees in the Kelvin scale.

Users of the class will only be able to change this value via the public interface – the public methods
that define the behaviour.

PUBLIC BEHAVIOUR

PRIVATE STATE
void setTemp(double,char)
temp
double getKelvin()

double getCelsius( )

V2 1
Task 1 Creating a Tester Project
Start Visual C# and create a new Console project on a flash drive (this will save problems with
permissions) called ADTExample.

This will automatically create a new class called Program that you will use to test your Temperature
ADT.

Task 2: Adding a Temperature Class


In the solution explorer add a new class called Temperature to your project,

the file should be called ‘Temperature.cs’

You should now see two files in the namespace ADTExample – you can switch between the files
using the tabs at the top of the editor.

V2 2
Your Temperature ADT will be defined in the file Temperature.cs – this allows the file to be copied
or imported into other projects.

In the file Temperature.cs add in the instance variable from the UML as shown below

class Temperature
{
/// <summary>
/// private instance variable stores temperature as kelvin
/// </summary>
private double temp;
}

V2 3
Task 3: Testing the default behaviour
Now use the file Program.cs to write a small tester program as shown below

Add the breakpoint as shown and then run the program. Move the cursor over the variable atemp and
note the value of the instance variable temp for the object aTemp in the space below.

temp

The program has used the built in default constructor to create a new instance object referred to with
the variable atemp. This has set the value of the instance variable to the default value corresponding to
its data type.

Now try editing the code to directly access the instance variable as shown below

static void Main(string[] args)


{
Temperature aTemp;
aTemp = new Temperature();
aTemp.temp = 12;
Console.ReadLine();
}

You should get an error message – note what it is below and give a reason why you think this
message has appeared.

V2 4
Delete the command atemp.temp = 12;

V2 5
Task 4: Overriding the Default Constructor
Constructors are class methods that allow you to create new instance objects and are accessed by
using the keyword new. A constructor has the same name as the class, but you can create as many
constructors as you need by changing the parameter set (the method signature).

In your temperature class override the default constructor as shown below.

public class Temperature


{
/// <summary>
/// stores temperature as kelvin
/// </summary>
private double temp;

/// <summary>
/// default constructor
/// sets temperature to 0K
/// </summary>
public Temperature()
{
temp = 0;
}
}

Now run your tester program and note what values the instance variables have when the breakpoint is
reached.

temp

Notice how the constructor

 Has the same name as the class


 Does not have a return type
 Has public scope

V2 6
Task 5: Add a public instance getter method

You should have noticed by now that you cannot directly access the contents of the private instance
variable temp and scale. This can make the testing a little frustrating as you have to use the
debugger to examine the contents. In this task you will add a public getter method that will return
the value in the instance variable temp.

Add the following method to your Temperature class below the constructors.

/// <summary>
/// returns a string showing values in private members
/// helper method for testing purposes only
/// </summary>
/// <returns>string representation of state in instance object</returns>
public string getPrivateValues()
{
return string.Format("value in temp: {0:F2}", temp);
}

Now edit you Main method in Program.cs as shown below

static void Main(string[] args)


{
Temperature atemp;
atemp = new Temperature();
Console.WriteLine(atemp.getPrivatevalues());
Console.ReadLine();
}

Remove the breakpoint (if still present) and run the program and note how the program now displays
the contents of the private attribute. This should help your testing in the next task.

V2 7
Task 6: Adding More Constructors
In this task you are going to add another constructor that takes in a double and a char (this constructor
has two parameters). It then sets the value of the instance variable temp to an appropriate value
depending on the values entered as arguments to the parameters. The second parameter should be
called with one of three possible value

 ‘c’ or ‘C’ –centigrade scale


 ‘k’ or ‘K’ – kelvin scale
 ‘f’ or ‘F’ – kelvin scale
If the user enters an invalid scale, the temperature should be set to Kelvin for the moment.

Constructor signature

/// <summary>
/// Constructor sets temp to temperature in kelvin
/// depending on values in t and s
/// </summary>
/// <param name="t">temperature in scale</param>
/// <param name="s">scale to convert from</param>
public Temperature(double t,char s)
{
//TO DO
}

There is a problem here – absolute zero is 0°K which is the same as -273°C or -459.4 °F. Spend a bit
of time trying to think of a solution to this problem.
(Note: Strictly 0°K is -273.15°C, but for this exercise we’ll stick to the rounded figure!)
Use the following algorithm to make your constructor more valid.

Convert character in s to uppercase


If character in s is not valid (F,C or K) then
Set character to ‘K’ -
Else
If character in s is ‘F’ then
Convert to Celsius
Set t to ((t-32)/1.8)
If character is ‘C’or’F’
Convert to kelvin
Set t to t+273
If t is less than 0
Impossible temperature so
Set temp to 0
Else
Set temp to t

Test your constructor using the following test cases

Arguments Expected values Actual values Test Passed


Arg1 Arg2 temp temp Y/N

V2 8
-273 C 0
-289 C 0
100 F 310.78
67 K 67

Add in another constructor with the following definition

public Temperature ( double d)


{

This should simply set the value in temp to either the value in d or to zero if the value in d is less than
0. This constructor assumes kelvin

Edit your Main method in Program.cs to test your new constructor.

V2 9
Task 7 Adding some public behaviour – getter methods
In this task you are going to add some public behaviour to your Temperature class. You may well
need to use the following two formulas.

Formula for converting Fahrenheit to Celsius


Temp C = (Temp F – 32) / 1.8
Formula for converting Celsius to Fahrenheit
Temp F = Temp C * 1.8 + 32;

Part a
Add in the following two methods and then design a set of test cases to ensure they are working correctly.

Note: There are 3 syntax errors and 1 logic error that you should fix!

/// <summary>
/// returns a double representing degrees celcius
/// </summary>
/// <returns>temperature in celcius</returns>
public double getCelsius()
{
double t = temp
t = t + 273;
return t;
}

/// <summary>
/// returns a string representation of temperature in celcius
/// </summary>
/// <returns>string representation of temperature in celcius</returns>
public string getstrCelsius(
{
//note how you can call other public methods
double t = getCelsius();
//note how string.Format can be used to
//format a string in a manner similar to
//that used in Console.WriteLine( )
//also note how you can use \x00B0 (UTF-16 code for ° symbol)
return String.Format("{0:f1}\x00B0 C", t);
}

Part B
Given the examples above complete the implementation for the following getter methods.
double getKelvin( ) – returns a double representing degrees Kelvin

double getFahrenheit( ) – returns a double representing degrees Fahrenheit

string getstrKelvin( ) – returns a string representing degrees Kelvin

string getstrFahrenheit( ) – returns a string representing degrees Fahrenheit

V2 10
Task 8 – adding a setter method
In this task you will add a setter method that will throw an Exception if the user tries to set a temperature that is
illegal.

Note: there is one logic error, but this should be easy to spot!

/***************************
* add an appropriate comment using xml comments
*****************************/
public void setTemp(double d, char c)
{
c = char.ToLower(c);
if (c == 'F')
{
//convert to celsius
d = (d - 32) / 1.8;
}
if (c == 'C' || c == 'F')
{
//convert to kelvin
d = d + 273;
}

if ((c != 'F' && c != 'C' && c != 'F') || d < 0)


throw new Exception("unkown temprature");

this.temp = d;

Use the following test harness in program.cs to test your program.


static void Main(string[] args)
{
Temperature atemp;
atemp = new Temperature();
try
{
Console.WriteLine("temp set to 100C");
atemp.setTemp(100, 'c');
Console.WriteLine("Kelvin\tCelsius\tFahrenheit");
Console.WriteLine("{0:f1}\t{1:f1}\t{2:f1}", atemp.getKelvin(),
atemp.getCelsius(), atemp.getFahrenheit());
Console.WriteLine("temp set to 100F");
atemp.setTemp(100, 'F');
Console.WriteLine("Kelvin\tCelsius\tFahrenheit");
Console.WriteLine("{0:f1}\t{1:f1}\t{2:f1}", atemp.getKelvin(),
atemp.getCelsius(), atemp.getFahrenheit());
Console.WriteLine("temp set to -400C - expect error");
atemp.setTemp(-400, 'c');
Console.WriteLine("Kelvin\tCelsius\tFahrenheit");
Console.WriteLine("{0:f1}\t{1:f1}\t{2:f1}", atemp.getKelvin(),
atemp.getCelsius(), atemp.getFahrenheit());
}
catch (Exception e)
{
Console.WriteLine("Error thrown " + e.Message);
}
Console.ReadLine();
}

How could you sort the similar the problem with your constructor on p6

V2 11
Task 9: Coding Class Methods
In tasks 7 and 8 you added some public instance methods to your class. These are available to all
objects created of the type Temperature. In addition, you can add class methods that can be called
from the one class meta object. You have used some of these before e.g.

int.Parse(string)

These need to be declared as static methods and are not available to instance objects. In this exercise
you will add a static Parse method to your Temperature class.

/// <summary>
/// static Parse method
/// reads in string in format ddd.dds
/// where s can be f,F,C,c,K or k
/// and converts to new temperature object
/// throws exception if illegal
/// </summary>
/// <param name="st">string in format ddd.dds where s can be f,F,C,c,K or k </param>
/// <returns>new Temperature object</returns>
public static Temperature Parse(string st)
{
char c = 'e';//set to illegal character
double d = 0.00;
if (st.Length > 0)
{
//get last character
c = st[st.Length - 1];
//remove last character
st = st.Remove(st.Length - 1);
}
try
{
d = double.Parse(st);//will throw error if cannot parse
Temperature t = new Temperature();
t.setTemp(d, c);//will throw error if invalid arguments
return (t);
}
catch (Exception e)
{
throw e;//Exception passed on
}
}

Notice how the method uses double.Parse( ) and the Temperature instance method setTemp( ) to
discover if the value entered is invalid. If an Exception is thrown, it is caught and thrown.

In UML class daigrams static methods and static attributes are underlined e.g.

+Temperature Parse( string )

Test the method using code like the Main( ) of program shown on the next page.

V2 12
Tester Code for Temperature Parse method

static void Main(string[] args)


{
string strValue;
Temperature t;
Console.WriteLine("enter a temperature in format 12C, 12F or 12K");
strValue = Console.ReadLine();
try
{
t = Temperature.Parse(strValue);
Console.WriteLine("Temp entered {0:f1}", t.getstrKelvin());
}
catch (Exception e)
{
Console.WriteLine("error thrown " + e.Message);
}
}

Run the code with a range of values to see how the method throws an Exception if the string entered
cannot parse to a temperature.

Task 10: Overriding the ToString( ) Method

All classes in C# inherit certain methods from a super class called Object. One of the methods
inherited is the ToString( ) method. This method is used by methods such as Console.WriteLine( )to
represent the contents of an object as a string.

Edit your Main method in program.cs as shown below, run it and note what happens.
static void Main(string[] args)
{
Temperature mytemp = new Temperature(100, 'c');
Console.WriteLine("value of mytemp: " + mytemp);
Console.ReadLine();
}

What happens?__________________________________

Wouldn’t it be nicer if it displayed 100°C

Add the following method to your Temperature class – note how the keyword override is used.
override public string ToString()
{
return getstrCelsius();
}

The default ToString method will now display the temperature in celcius.

Now try the program again and note what happens

V2 13
Task 11: Overriding Operators (supported in C# and C++ not Java)
Wouldn’t it be nice if you could add and compare Temperature variables using the standard operators
used with primitive data types?

In C# you can – you use static overrides of the operators!!

Add the following 3 overriden operators to your Temperature class


/***Comparison operators have to be overriden in pairs

Notice how methods can access private members directly***/

public static bool operator <(Temperture t1, Temperture t2)


{
return (t1.temp < t2.temp);
}

public static bool operator >(Temperature t1, Temperture t2)


{
return (t1.temp > t2.temp);
}

/**the assignment operator = ***/


public static implicit operator Temperature(string st)
{
Temperature temp = new Temperature();
try
{
temp = Temperature.Parse(st);
}
catch (Exception e)
{
throw e;
}
return temp;
}

Test this with the following Main method


static void Main(string[] args)
{
Temperature t1, t2;
t1 = "12C";
t2 = "45F";
if (t1<t2)
Console.WriteLine(t1 + " is less than " + t2);
else
Console.WriteLine(t1 + " is less than " + t2);
Console.ReadLine();
}

Exercise: Try overriding the following operators and write short test programs
 != and == operators
 = assignment for a double (should set to Kelvin)
 The four basic arithmetic operators – these are similar in style to the assignment operator but
you should really search for an example either in the C# help files or the Internet - Good
Luck!

V2 14

You might also like