Presentation is loading. Please wait.

Presentation is loading. Please wait.

Operator Overloading Week 5.

Similar presentations


Presentation on theme: "Operator Overloading Week 5."— Presentation transcript:

1 Operator Overloading Week 5

2 Operator Overloading There are various C# built-in types, such as integer (int) and Boolean (bool), and there are also various operators that allow these data types to be manipulated arithmetic: + - * / % comparisons: == != < <= > >= logical: && || ! & | ^ Using most of these operators with basic types is simple and intuitive Using these operators with created classes will cause errors

3 Designing the Fraction Class
Create a new type called Fraction to store fractional numbers: Fraction first = new Fraction(1, 2); //create ½ Fraction second = new Fraction(3, 4); //create ¾ Constructors take the first parameter as the numerator, and the second parameter as the denominator To give the Fraction class all the functionality of the built-in types, there will be the need to perform arithmetic on instances of Fraction Add two Fractions, multiple them, etc Conversions to or from built-in types should also be available

4 It would be much better to be able to write:
Each of these operations could be implemented using methods, but it’s not intuitively obvious: Fraction sum = first.Add(second); This is hard to read It’s not how a user would immediately expect addition to work It doesn’t look like addition It would be much better to be able to write: Fraction sum = first + second; This is intuitive and easy to use It is consistent with how built-in operators are added

5 Using the operator Keyword
C# allows methods and constructors to be overloaded It also enables most operators to be overloaded as well to make them sensitive to the context in which they are used The syntax is to write the keyword operator followed by the operator to overload Operators are public and static methods The return value of an operator represents the result of an operation The operator’s parameters are the operands

6 Define an addition operator for a Fraction class the same as any other method but with a difference:
Instead of a method name, use operator+ Addition is a binary operation, requiring two operands, so the operator+ method will require two parameters of type Fraction Addition has a result, requiring a return value of type Fraction public static Fraction operator +(Fraction lhs, Fraction rhs) The parameters of lhs and rhs stand for left-hand side and right-hand side

7 public class Fraction { private int numerator; private int denominator; //create a fraction by passing in the numerator and denominator public Fraction(int numerator, int denominator) this.numerator = numerator; this.denominator = denominator; } //return a string representation of the fraction public override string ToString() string s = numerator.ToString() + "/" + denominator.ToString(); return s;

8 //overloaded + takes two fractions and returns their sum public static Fraction operator +(Fraction lhs, Fraction rhs) { //like fractions (shared denominators) can be added by adding their numerators if(lhs.denominator == rhs.denominator) return new Fraction(lhs.numerator + rhs.numerator, lhs.denominator); //simplistic solution for unlike fractions is to cross-multiply: // 1/2 + 3/4 == ((1*4) + (3*2)) / (2*4) == 10/8 //this method does not reduce int firstProduct = lhs.numerator * rhs.denominator; int secondProduct = rhs.numerator * lhs.denominator; return new Fraction(firstProduct + secondProduct, lhs.denominator * rhs.denominator); }

9 Output would be: public class Tester { public void Run()
Fraction f1 = new Fraction(3, 4); Console.WriteLine("f1: {0}", f1); Fraction f2 = new Fraction(2, 4); Console.WriteLine("f2: {0}", f2); Fraction f3 = f1 + f2; //test the overloaded addition operator Console.WriteLine("f1 + f2 = f3: {0}", f3); } public static void Main() Tester t = new Tester(); t.Run(); Output would be: f1: 3/4 f2: 2/4 f1 + f2 = f3: 5/4

10 Creating Useful Operators
Operator overloading can make code more intuitive and allow them to be used similar to built-in types However, they way they are used should make sense Operators that don’t naturally follow their traditional meanings will be confusing Use operator overloading when it makes an application clearer than accomplishing the same operations with explicit method calls

11 Overload operators to perform the same function or similar functions on class objects as the operators perform on objects of simple types At least one argument of an overloaded operator method must be a reference to an object of the class in which the operator is overloaded This prevents programmers from changing how operators work on simple types

12 The Equals Operator It’s very common to overload the == operator to determine whether two objects are equal What “equal” means is up to the programmer, although the criteria should be reasonable Two Employee objects might be equal if they have the same name or perhaps if the same employee ID Overloading the == operator works the same way as overloading any other operator public static bool operator ==(Fraction lhs, Fraction rhs) The == operator always returns a Boolean value (true or false)

13 C# insists that if the equals operator is overloaded, then the not-equals (!=) operator must also be overloaded It’s good programming practice to have the inequality operator delegate its work to the equality operator The != operator will return the opposite of the value of the == operator Similarly, the less than (<) and greater than (>) operators must be paired as must the less than or equal to (<=) and greater than or equal to (>=) operators

14 The Object class offers a virtual method called Equals()
If the equals operator is overloaded, it is recommended that the Equals() method also be overridden Overriding the Equals() method allows the class to be compatible with other .NET languages that do not overload operators but still support method overloading That way, if the == operator can’t be used, the Equals() method is still available public virtual bool Equals(object o) Ensure that one Fraction object is being compared with another Fraction object, otherwise they cannot be equal

15 //add these methods to the existing Fraction class //test whether two Fractions are equal public static bool operator ==(Fraction lhs, Fraction rhs) { if(lhs.denominator == rhs.denominator && lhs.numerator == rhs.numerator) return true; //code here to handle unlike Fractions return false; } //delegates to operator == public static bool operator !=(Fraction lhs, Fraction rhs) return !(lhs == rhs); //just the opposite of == //tests for same types, then delegates public override bool Equals(object o) if(!(o is Fraction)) //objects have to be the same type to be equal return this == (Fraction)o; //cast the object as a Fraction and delegate to ==

16 Generates this output:
//can now add to the Run() method Fraction f4 = new Fraction(5, 4); if(f4 == f3) Console.WriteLine("f4: {0} == f3: {1}", f4, f3); if(f4 != f2) Console.WriteLine("f4: {0} != f2: {1}", f4, f2); if(f4.Equals(f3)) Console.WriteLine("{0}.Equals({1})", f4, f3); Generates this output: f4: 5/4 == f3: 5/4 f4: 5/4 != f2: 2/4 5/4.Equals(5/4)

17 Conversion Operators C# will convert an int to a long implicitly, but will only allow a long to be converted to an int explicitly The conversion from int to long is implicit because any int will fit into a long Conversion from long to int must be explicit because it is possible to lose information in the conversion It would be useful for Fraction objects to be converted to intrinsic types (such as int) and back Given an int, implicit conversion to a Fraction can be supported because any whole value is equal to that value over 1 (15 == 15/1)

18 Given a Fraction, an explicit conversion back to an integer might be provided with the understanding that some information might be lost The Fraction 9/4 might be converted to the integer value 2 (truncating to the nearest whole number) To implement the conversion operator, the keyword operator is still used, but instead of a symbol to override, the type to be converted to is used instead public static implicit operator Fraction(int theInt) Use the implicit operator when the conversion is guaranteed to succeed and no information will be lost, otherwise, use the explicit operator instead

19 //add these methods to the existing Fraction class //overload the constructor to create a fraction from a whole number public Fraction(int wholeNumber) { numerator = wholeNumber; //any whole number over 1 is a Fraction denominator = 1; } //converts ints to Fractions implicitly public static implicit operator Fraction(int theInt) return new Fraction(theInt); //invoke constructor for a new Fraction //convert Fractions to ints explicitly public static explicit operator int(Fraction theFraction) return theFraction.numerator / theFraction.denominator; //return an int

20 Generates this output:
//can now add to the Run() method Fraction f5 = f4 + 5; //implicit conversion of 5 to a Fraction Console.WriteLine("f4 + 5 = f5: {0}", f5); int truncated = (int)f5; //explicit conversion of f5 to an int Console.WriteLine("When you truncate f5 you get {0}", truncated); Generates this output: f4 + 5 = f5: 25/4 When you truncate f5 you get 6 The cast from an int to a Fraction is perfectly safe, so it can be implicit The implementation of this is to create a new Fraction object and to return it The implicit cast operator causes the constructor to be invoked


Download ppt "Operator Overloading Week 5."

Similar presentations


Ads by Google