1 / 20

Operator Overloading

Operator Overloading. Week 5. 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: == != < <= > >=

rchandler
Télécharger la présentation

Operator Overloading

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

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: Fractionfirst = new Fraction(1, 2); //create ½ Fractionsecond = 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. 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 publicstaticFractionoperator +(Fraction lhs, Fraction rhs) • The parameters of lhs and rhs stand for left-hand side and right-hand side

  7. publicclassFraction { privateint numerator; privateint denominator; //create a fraction by passing in the numerator and denominator publicFraction(int numerator, int denominator) { this.numerator = numerator; this.denominator = denominator; } //return a string representation of the fraction publicoverridestring ToString() { string s = numerator.ToString() + "/" + denominator.ToString(); return s; }

  8. //overloaded + takes two fractions and returns their sum publicstaticFractionoperator +(Fraction lhs, Fraction rhs) { //like fractions (shared denominators) can be added by adding their numerators if(lhs.denominator == rhs.denominator) returnnewFraction(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; returnnew Fraction(firstProduct + secondProduct, lhs.denominator * rhs.denominator); } }

  9. publicclassTester { publicvoid Run() { Fraction f1 = newFraction(3, 4); Console.WriteLine("f1: {0}", f1); Fraction f2 = newFraction(2, 4); Console.WriteLine("f2: {0}", f2); Fraction f3 = f1 + f2; //test the overloaded addition operator Console.WriteLine("f1 + f2 = f3: {0}", f3); } publicstaticvoid Main() { Tester t = newTester(); 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 anapplication clearer than accomplishing the sameoperations 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 publicstaticbooloperator ==(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 publicvirtualbool 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 publicstaticbooloperator ==(Fraction lhs, Fraction rhs) { if(lhs.denominator == rhs.denominator && lhs.numerator == rhs.numerator) returntrue; //code here to handle unlike Fractions returnfalse; } //delegates to operator == publicstaticbooloperator !=(Fraction lhs, Fraction rhs) { return !(lhs == rhs); //just the opposite of == } //tests for same types, then delegates publicoverridebool Equals(object o) { if(!(o isFraction)) //objects have to be the same type to be equal returnfalse; returnthis == (Fraction)o; //cast the object as a Fraction and delegate to == }

  16. //can now add to the Run() method Fraction f4 = newFraction(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 longimplicitly, but will only allow a long to be converted to an intexplicitly • 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 Fraction9/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 publicstaticimplicitoperatorFraction(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 publicFraction(int wholeNumber) { numerator = wholeNumber; //any whole number over 1 is a Fraction denominator = 1; } //converts ints to Fractions implicitly publicstaticimplicitoperatorFraction(int theInt) { returnnewFraction(theInt); //invoke constructor for a new Fraction } //convert Fractions to ints explicitly publicstaticexplicitoperatorint(Fraction theFraction) { return theFraction.numerator / theFraction.denominator; //return an int }

  20. //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

More Related