• No results found

Lecture 6: Operator Overloading, Indexers, and Properties

N/A
N/A
Protected

Academic year: 2020

Share "Lecture 6: Operator Overloading, Indexers, and Properties"

Copied!
25
0
0

Loading.... (view fulltext now)

Full text

(1)

Lecture 6:

Operator Overloading,

Indexers, and

(2)

Operator Overloading

Operator overloading is a process that allows to define the meaning

of an operator relative to a class.

⚫ When an operator is overloaded, none of its original meaning is lost. It is simply that a new operation, relative to a specific class, is added. ⚫ For example, a class that defines a linked list might use the +

operator to add an object to the list.

Overloading the + to handle a linked list, for example, does not cause its meaning relative to integers (that is, addition) to be changed.

To overload an operator, use the operator keyword to define an

(3)

The General Forms of an Operator Method

There are two forms of operator methods: one for unary operators and one for binary operators. The general form for each is shown here:

// General form for overloading a unary operator.

public static ret-type operator op(param-type operand)

⚫ {

⚫ // operations

⚫ }

// General form for overloading a binary operator.

public static ret-type operator op(param-type1 operand1, param-type2

operand2)

⚫ {

⚫ // operations

(4)

The General Forms of an Operator Method

Here, the operator that you are overloading, such as + or /,

is substituted for the op.

The ret-type is the type of value returned by the specified

operation. Although it can be of any type you choose, the return value is often of the same type as the class for

which the operator is being overloaded.

For unary operators, the operand is passed in operand. For

binary operators, the operands are passed in operand1 and

(5)

Overloading Binary Operators

⚫ Lets’s start with an example that overloads two binary

operators: the + and the –.

The following program creates a class called ThreeD,

which maintains the coordinates of an object in three-dimensional space.

The overloaded + adds the individual coordinates of one

ThreeD object to another. The overloaded – subtracts the

(6)

Example of Binary Operator

⚫ using System;

⚫ class ThreeD {

⚫ int x, y, z;

⚫ public ThreeD() { x = y = z = 0; }

⚫ public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

⚫ public static ThreeD operator +(ThreeD op1, ThreeD op2)

⚫ {

⚫ ThreeD result = new ThreeD(); op1:

⚫ result.x = op1.x + op2.x; // These are integer additions op2:

⚫ result.y = op1.y + op2.y; // and the + retains its original

⚫ result.z = op1.z + op2.z; // meaning relative to them. result

⚫ return result;

⚫ }

public static ThreeD operator -(ThreeD op1, ThreeD op2)

⚫ {

⚫ ThreeD result = new ThreeD();

⚫ result.x = op1.x - op2.x; // these are integer subtractions

⚫ result.y = op1.y - op2.y;

⚫ result.z = op1.z - op2.z;

⚫ return result;

⚫ }

X:1 Y:2 Z:3

X:10 Y:10 Z:10

(7)

⚫ // Show X, Y, Z coordinates.

⚫ public void Show()

⚫ {

⚫ Console.WriteLine(x + ", " + y + ", " + z);

⚫ }

⚫ }

⚫ class ThreeDDemo { ⚫ static void Main() {

⚫ ThreeD a = new ThreeD(1, 2, 3); a: ⚫ ThreeD b = new ThreeD(10, 10, 10); b: ⚫ ThreeD c = new ThreeD();

⚫ Console.Write("Here is a: "); c: ⚫ a.Show(); ⚫ Console.WriteLine(); ⚫ Console.Write("Here is b: "); ⚫ b.Show(); ⚫ Console.WriteLine();

⚫ c = a + b; // add a and b together c: ⚫ Console.Write("Result of a + b: "); ⚫ c.Show(); X:1 Y:2 Z:3 X:10 Y:10 Z:10 X:0 Y:0 Z:0 X:11 Y:12 Z:13

(8)

⚫ Console.WriteLine();

⚫ c = a + b + c; // add a, b and c together

⚫ Console.Write("Result of a + b + c: "); ⚫ c.Show(); ⚫ Console.WriteLine(); ⚫ c = c - a; // subtract a ⚫ Console.Write("Result of c - a: "); ⚫ c.Show(); ⚫ Console.WriteLine(); ⚫ c = c - b; // subtract b ⚫ Console.Write("Result of c - b: "); ⚫ c.Show(); ⚫ Console.WriteLine(); ⚫ } ⚫ }

⚫ This program produces the following output:

⚫ Here is a: 1, 2, 3 ⚫ Here is b: 10, 10, 10 ⚫ Result of a + b: 11, 12, 13 ⚫ Result of a + b + c: 22, 24, 26 ⚫ Result of c - a: 21, 22, 23 ⚫ Result of c - b: 11, 12, 13

(9)

Overloading Unary Operators

⚫ The unary operators are overloaded just like the binary operators. The main difference, is that there is only one operand. For example, here is a method that overloads the unary minus for the ThreeD

class:

⚫ // Overload unary -.

⚫ public static ThreeD operator -(ThreeD op)

⚫ {

⚫ ThreeD result = new ThreeD();

⚫ result.x = -op.x; ⚫ result.y = -op.y; ⚫ result.z = -op.z; ⚫ return result;

(10)

⚫ // Overload unary ++.

⚫ public static ThreeD operator ++(ThreeD op)

⚫ {

⚫ ThreeD result = new ThreeD();

⚫ // Return the incremented result. ⚫ result.x = op.x + 1; ⚫ result.y = op.y + 1; ⚫ result.z = op.z + 1; ⚫ return result; ⚫ } ⚫ // Show X, Y, Z coordinates.

⚫ public void Show()

⚫ {

⚫ Console.WriteLine(x + ", " + y + ", " + z);

⚫ }

(11)

⚫ class ThreeDDemo {

⚫ static void Main() {

⚫ ThreeD a = new ThreeD(1, 2, 3);

⚫ ThreeD b = new ThreeD(10, 10, 10);

⚫ ThreeD c = new ThreeD();

⚫ Console.Write("Here is a: ");

⚫ a.Show();

⚫ Console.Write("Here is b: ");

⚫ b.Show();

⚫ c = a + b; // add a and b together

⚫ Console.Write("Result of a + b: ");

(12)

⚫ c = -a; // assign -a to c ⚫ Console.Write("Result of -a: "); ⚫ c.Show(); ⚫ Console.WriteLine(); ⚫ c = a++; // post-increment a ⚫ Console.WriteLine("Given c = a++"); ⚫ Console.Write("c is "); ⚫ c.Show(); ⚫ Console.Write("a is "); ⚫ a.Show(); ⚫ // Reset a to 1, 2, 3 ⚫ a = new ThreeD(1, 2, 3); ⚫ Console.Write("\nResetting a to "); ⚫ a.Show(); ⚫ c = ++a; // pre-increment a ⚫ Console.WriteLine("\nGiven c = ++a"); ⚫ Console.Write("c is "); ⚫ c.Show(); ⚫ Console.Write("a is "); ⚫ a.Show(); ⚫ } ⚫ }

(13)

⚫ The output from the program is shown here: ⚫ Here is a: 1, 2, 3 ⚫ Here is b: 10, 10, 10 ⚫ Result of a + b: 11, 12, 13 ⚫ Result of -a: -1, -2, -3 ⚫ Given c = a++ ⚫ c is 1, 2, 3 ⚫ a is 2, 3, 4 ⚫ Resetting a to 1, 2, 3 ⚫ Given c = ++a ⚫ c is 2, 3, 4 ⚫ a is 2, 3, 4

(14)

Overloading the Relational

Operators

The relational operators, such as = = or <, can also be

overloaded.

Usually, an overloaded relational operator returns a true

or false value.

⚫ This is in keeping with the normal usage of these

operators and allows the overloaded relational operators to be used in conditional expressions.

Here is a version of the ThreeD class that overloads the <

(15)

⚫ // Overload < and >.

⚫ using System;

⚫ // A three-dimensional coordinate class.

⚫ class ThreeD {

⚫ int x, y, z; // 3-D coordinates

⚫ public ThreeD() { x = y = z = 0; }

⚫ public ThreeD(int i, int j, int k) { x = i; y = j; z = k; } ⚫ // Overload <.

⚫ public static bool operator <(ThreeD op1, ThreeD op2)

⚫ {

⚫ if(Math.Sqrt(op1.x * op1.x + op1.y * op1.y + op1.z * op1.z) <

⚫ Math.Sqrt(op2.x * op2.x + op2.y * op2.y + op2.z * op2.z))

⚫ return true; ⚫ else

⚫ return false;

(16)

⚫ // Overload >.

⚫ public static bool operator >(ThreeD op1, ThreeD op2)

⚫ {

⚫ if(Math.Sqrt(op1.x * op1.x + op1.y * op1.y + op1.z * op1.z) >

⚫ Math.Sqrt(op2.x * op2.x + op2.y * op2.y + op2.z * op2.z))

⚫ return true; ⚫ else

⚫ return false;

⚫ }

⚫ // Show X, Y, Z coordinates.

⚫ public void Show()

⚫ {

⚫ Console.WriteLine(x + ", " + y + ", " + z);

⚫ }

(17)

⚫ class ThreeDDemo {

⚫ static void Main() {

⚫ ThreeD a = new ThreeD(5, 6, 7);

⚫ ThreeD b = new ThreeD(10, 10, 10);

⚫ ThreeD c = new ThreeD(1, 2, 3);

⚫ ThreeD d = new ThreeD(6, 7, 5);

⚫ Console.Write("Here is a: "); ⚫ a.Show(); ⚫ Console.Write("Here is b: "); ⚫ b.Show(); ⚫ Console.Write("Here is c: "); ⚫ c.Show(); ⚫ Console.Write("Here is d: "); ⚫ d.Show(); ⚫ Console.WriteLine()

(18)

⚫ if(a > c) Console.WriteLine("a > c is true");

⚫ if(a < c) Console.WriteLine("a < c is true");

⚫ if(a > b) Console.WriteLine("a > b is true");

⚫ if(a < b) Console.WriteLine("a < b is true");

⚫ if(a > d) Console.WriteLine("a > d is true");

⚫ else if(a < d) Console.WriteLine("a < d is true");

⚫ else Console.WriteLine("a and d are same distance from

origin");

⚫ }

(19)

⚫ The output from this program is shown here: ⚫ Here is a: 5, 6, 7 ⚫ Here is b: 10, 10, 10 ⚫ Here is c: 1, 2, 3 ⚫ Here is d: 6, 7, 5 ⚫ a > c is true ⚫ a < b is true

(20)

⚫ There is an important restriction that applies to

overloading the relational operators: You must overload them in pairs. For example, if you overload <, you must also overload >, and

⚫ vice versa. The operator pairs are

⚫ = = !=

⚫ < >

⚫ <= >=

Thus, if you overload <=, you must also overload >=, and

if you overload = =, you must also

(21)

Operator Overloading Tips and

Restrictions

⚫ The action of an overloaded operator as applied to the

class for which it is defined need not bear any relationship to that operator’s default usage

⚫ For clarity, it is best when its new meaning is related to its

original meaning.

⚫ You cannot alter the precedence of any operator.

⚫ You cannot alter the number of operands required by the

operator, although

⚫ There are several operators that you cannot overload.

Perhaps most significantly, you cannot overload any assignment operator, including the compound

(22)

Indexers

Array indexing is performed using the [ ] operator.

It is possible to overload the [ ] operator for classes that

you create, but you don’t use an operator method.

Instead, you create an indexer. An indexer allows an

object to be indexed like an array.

⚫ The main use of indexers is to support the creation of

specialized arrays that are subject to one or more constraints.

(23)

One-dimensional indexers have this general

form:

⚫ We will begin with one-dimensional indexers. One-dimensional

indexers have this general

⚫ form:

element-type this[int index] {

⚫ // The get accessor.

⚫ get {

// return the value specified by index

⚫ }

⚫ }

⚫ // The set accessor.

⚫ set {

// set the value specified by index

(24)

Properties

⚫ Properties are similar to indexers. A property consists of a

name, along with get and set accessors. The accessors are used to get and set the value of a variable. The key benefit of a property is that its name can be used in expressions and assignments like a normal variable, but in actuality, the get and set accessors are automatically invoked.

This is similar to the way that an indexer’s get and set

(25)

⚫ The general form of a property is shown here:

type name {

⚫ get {

⚫ // get accessor code

⚫ }

⚫ set {

⚫ // set accessor code

⚫ }

⚫ }

Here, type specifies the type of the property, such as int, and

name is the name of the property.

Once the property has been defined, any use of name results in

a call to its appropriate accessor. The set accessor

automatically receives a parameter called value that contains the value being assigned to the property.

References

Related documents

 In order for a candidate's name to be placed on the ballot, a candidate must file a Campaign Registration Statement (ETHCF-1), a Declaration of Candidacy (EL-162), and

– protected : Derived classes and friend s can access protected members of the base

calycularis colonies under extreme aquarium conditions, further investigations are required to confirm whether polyp bail-out also occurs in natural conditions, and whether

Embodied within the Cartesian view is the idea that the activities of the mind cannot violate the conservation laws of physics but only effect choices, i.e.,

Skippers of vessels left overnight must make arrangements for leaving the dock or having their vessels returned to their moorings no later than one hour after launch service

Please cite this article as: Nikpouraghdam M, Farahani AJ, Alishiri G, Heydari S, Ebrahimnia M, Samadinia H, Sepandi M, Jafari NJ, Izadi M, Qazvini A, Dorostkar R, Tat M, Shahriary

Investigating the results for all discharge values revealed that adding suspended flow load for the fourth time about 12000 ppm causes higher decrease in outflow passing through

1 example_wrap.c generated C code, 2 example_wrap.o compiled object file, 3 _example.so shared object file, and 4 example.py Python code for wrapper... Summary and