Nạp chồng toỏn tử (Overloading operator)

Một phần của tài liệu Giáo trình lập trình windowns form với c net tập 1 TS lê trung hiếu, ths nguyễn thị minh thi (Trang 133)

Phương thức nạp chồng toỏn tử là một thành viờn của lớp, để định nghĩa một phộp toỏn sử dụng cho đối tượng của lớp. Cú ba kiểu

phộp toỏn cú thể nạp chồng: một ngụi (unary operator), hai ngụi

(binary operator) và phộp chuyển kiểu. Cỳ phỏp phương thức nạp

chồng ba kiểu phộp toỏn này như sau:

BổTừ Kiểu Operator PhộpToỏnMộtNgụi(ThamĐối){ //Thõn phương thức

}

BổTừ Kiểu Operator PhộpToỏnHaiNgụi(Tham Đối1, ThamĐối2){

//Thõn phương thức

}

BổTừ implicit/ explicitOperator

KiểuChuyểnĐổi(ThamĐối){

//Thõn phương thức

}

Trong đú:

 Bổ từ (Modifier) là cỏc từ khúa public, static hay extern.

Từ khoỏ extern chỉ ra rằng phương thức được gọi tồn tại trong một thư viện DLL

 Một phương thức nạp chồng toỏn tử phải là một phương thức

tĩnh static

 Kiểu (Data type) là kiểu dữ liệu trả về của phộp toỏn

 Phộp toỏn một ngụi là phộp toỏn cú một toỏn hạng như + - ! ~ ++ --

 Phộp toỏn hai ngụi là phộp toỏn cú hai toỏn hạng như + - * / % & | ^ << >> == != > < >= <=

 Khi nạp chồng phộp toỏn so sỏnh, phải nạp chồng cho phộp toỏn trỏi ngược của nú, vớ dụ nạp chồng phộp so sỏnh ==, ta

phải nạp chồng cả phộp so sỏnh !=, nếu khụng chương trỡnh sẽ bỏo lỗi.

 Kiểu chuyển đổi (Convert type) là kiểu dữ liệu cần chuyển đổi thành.

 implicit/ explicit là từ khúa cho phộp chuyển kiểu mặc định hay tường minh.

Vớ dụ:

Chuyển kiểu mặc định phõn số a thành double: double d = a;

Chuyển kiểu tường minh phõn số a thành double: double d = (double) a;

 Tham đối (Parameter) cú dạng: Kiểu ThamĐối

 Thõn phương thức phải cú lệnh trả về giỏ trị cho phộp toỏn

Vớ dụ:Định nghĩa cỏc phộp toỏn cho lớp PhanSo

using System; class PhanSo {

int tu, mau; public int Tu { get { return tu; } }

public int Mau {

get {

return mau; }

public PhanSo(int tu, int mau) { this.tu = tu; this.mau = mau; } // Nạp chồng phộp cộng

public static PhanSo operator+(PhanSo a, PhanSo b) {

PhanSo tong = new PhanSo(a.tu * b.mau + b.tu * a.mau, a.mau * b.mau);

return tong; }

// Nạp chồng phộp nhõn

public static PhanSo operator*(PhanSo a, PhanSo b) {

return new PhanSo(a.tu * b.tu, a.mau * b.mau); }

// Nạp chồng phộp chuyển kiểu mặc định (implicit) thành double // Hay nạp chồng phộp chuyển kiểu tường minh (explicit thay cho implicit)

public static implicit operator double(PhanSo a) {

return (double) a.tu / a.mau; }

// Nạp chồng phộp so sỏnh ==

public static bool operator==(PhanSo a,PhanSo b) { if(a.tu*b.mau == a.mau*b.tu) return true; return false; } // Nạp chồng phộp so sỏnh !=

public static bool operator==(PhanSo a,PhanSo b) {

if (a.tu*b.mau != a.mau*b.tu) return true;

} }

class Test {

public static void Main() {

PhanSo a = new PhanSo(1, 2); PhanSo b = new PhanSo(3, 7); PhanSo c = new PhanSo(2, 3);

// Chuyển kiểu mặc định

Console.WriteLine(a * b + c); // Chuyển kiểu tường minh

Console.WriteLine((double)(a * b + c)); }

}

3.3. THUỘC TÍNH (PROPERTIES)

Thuộc tớnh là một đặc tớnh mới được giới thiệu trong ngụn ngữ C#. Đặc tớnh này cung cấp khả năng bảo vệ cỏc biến dữ liệu bờn trong một lớp bằng việc đọc và ghi chỳng thụng qua thuộc tớnh. Trong ngụn

ngữ khỏc, điều này cú thể được thực hiện thụng qua việc tạo cỏc phương thức truy cập (getter method hay accesser) và phương thức

thiết lập (setter method hay mutator).

Vớ dụ: class ViDu {

int a;

public int geta () {

return this.a; }

public void seta ( int a ) {

this.a = a; }

Cú thể được viết trong C# như sau, và cú thể dễ dàng truy cập

trực tiếp property bờn trong một chương trỡnh C#. class ViDu { int a; public int A { get { return this.a; } set {

// value là biến được tạo ra bởi trỡnh biờn dịch để thay thế

tham đối this.a = value; } } } class Test {

static void Main(string[] args) {

ViDu v = new ViDu(); v.A = 3;

Console.WriteLine(v.A); }

}

Lợi ớch của việc sử dụng thuộc tớnh (property) là cho phộp cỏc thành phần bờn ngoài cú thể truy cập thuộc tớnh một cỏch trực tiếp mà vẫn đảm bảo tớnh đúng gúi trong thiết kế hướng đối tượng.

Thuộc tớnh được tự động cài đặt (Auto-implemented properties):

C# 3.0 cho phộp cỏc thuộc tớnh của lớp được tự động cài đặt (auto- implemented properties). Đa số cỏc properties đều thực hiện cỏc thao tỏc như là ghi và đọc từ 1 biến private nào đú. Trong C# 3.0, nếu như

private thỡ chỉ cần khai bỏo ngắn gọn như sau, trỡnh biờn dịch sẽ tự động tạo biến private vụ danh tương tự khai bỏo tường minh. Để một

thuộc tớnh chỉ được đọc hay ghi giỏ trị trong lớp chứa thuộc tớnh,

thờm từ khúa private trước từ khúa get hay set.

Vớ dụ:

public class ViDu {

public int A { get; set; }

//public int A { get; private set; } }

Thuộc tớnh chỉ đọc (Read only property): Giả sử chỳng ta

muốn tạo lớp Time cung cấp một số thuộc tớnh static để hiển thị ngày hiện hành.

Vớ dụ: using System;

public class RightNow {

public static int Year; public static int Month; public static int Date; static RightNow() { DateTime dt = DateTime.Now; Year = dt.Year; Month = dt.Month; Date = dt.Day; } }

public class Tester {

static void Main() {

RightNow.Year = 2003;

Console.WriteLine("This year: {0}", RightNow.Year.ToString()); }

}

Biến thành viờn chỉ năm hiện hành Year đó được thay đổi thành

2003. Điều này thực sự khụng như mong muốn, cỏc biến tĩnh này

khụng được thay đổi. Nhưng khai bỏo hằng cũng khụng được vỡ biến

tĩnh khụng được khởi tạo cho đến khi phương thức khởi tạo tĩnh được thi hành. Do vậy C# cung cấp bổ sung từ khúa readonly cho

mục đớch này. Với vớ dụ trờn ta khai bỏo lại như sau:

public static readonly int Year; public static readonly int Month; public static readonly int Date;

Khi đú ta phải bỏ lệnh gỏn biến thành viờn Year, vỡ nếu

khụng sẽ bị bỏo lỗi:

// RightNow.Year = 2003;

3.4. THAM CHIẾU PHƯƠNG THỨC (DELEGATE)

Một tham chiếu phương thức (delegate) trong C# tương tự với

con trỏ hàm (function pointer) trong C++. Một delegate cho phộp chỳng ta định nghĩa một hay nhiều phương thức mà delegate tham chiếu đến. Đối tượng delegate được sử dụng để gọi một hay nhiều phương thức mà nú tham chiếu. Delegate là một kiểu tham chiếu đến phương thức, cư xử như phương thức đú, và cú thể được sử dụng như

bất kỳ phương thức với cỏc tham đối và giỏ trị trả về.

Cú ba bước định nghĩa và sử dụng delegate: Khai bỏo

(declaration), khởi tạo (initiation) và gọi phương thức tham chiếu bởi

delegate (invocation).

Khai bỏo delegate: Khai bỏo delegate giống như khai bỏo phương thức mà delegate tham chiếu đến

ĐiềuKhiểnTruyCập delegate Kiểu KiểuDelegate (DanhSỏchThamĐối);

Trong đú:

 Kiểu Delegate: Là tờn kiểu delegate

 Kiểu (Data type): Kiểu kết quả trả về của phương thức mà delegate tham chiếu đến

 Danh sỏch tham đối: Của phương thức mà delegate tham chiếu đến

Vớ dụ:

public delegate void SimpleDelegate(); public delegate void SimpleDelegate(int x);

Khởi tạo delegate: Khởi tạo một đối tượng Delegate, để chỉ ra cỏc phương thức mà delegate tham chiếu đến

KiểuDelegate TờnĐốiTượng = new KiểuDelegate (TờnPhươngThức);

 Tờn đối tượng: là tờn đối tượng delegate (delegate object)  Tờn phương thức: là phương thức mà delegate tham chiếu đến

Vớ dụ:

SimpleDelegate simpleDelegate = new SimpleDelegate(MyFunc);

Để thờm và xúa phương thức delegate tham chiếu đến, sử dụng

phộp toỏn += và -=

Vớ dụ:

SimpleDelegate simpleDelegate += new SimpleDelegate(MyFunc); SimpleDelegate simpleDelegate += new SimpleDelegate(MyFunc1); SimpleDelegate simpleDelegate -= new SimpleDelegate(MyFunc1);

Gọi phương thức tham chiếu bởi delegate:

TờnĐốiTượng(DanhSỏchThamĐối);

Tờn đối tượng: Là tờn đối tượng delegate (delegate object)

Vớ dụ:

simpleDelegate(); simpleDelegate(2);

Vớ dụ: Delegate tham chiếu đến phương thức khụng truyền

tham đối

using System;

namespace BasicDelegate {

// Khai bỏo delegate

public delegate void SimpleDelegate(); class TestDelegate

{

public static void MyFunc() {

Console.WriteLine("Phương thức được gọi bởi delegate");

}

public static void Main() {

// Khởi tạo delegate

SimpleDelegate simpleDelegate = new

SimpleDelegate(MyFunc); // Gọi delegate simpleDelegate(); } } }

Vớ dụ:Delegate tham chiếu đến phương thức cú truyền tham đối

using System;

namespace BasicDelegate {

// Khai bỏo delegate

public delegate void SimpleDelegate(int x); class TestDelegate

{

public static void MyFunc(int n) {

Console.WriteLine("Phương thức được gọi bởi delegate");

Console.WriteLine(n); }

public static void Main() {

// Khởi tạo delegate

SimpleDelegate simpleDelegate = new SimpleDelegate(MyFunc); // Gọi delegate

simpleDelegate(2); }

} }

Phương thức nặc danh (Anonymous method): Trong phiờn bản

trước của C# 2.0, ta chỉ cú thể khai bỏo delegate tham chiếu đến phương thức đặt tờn (named method). C# 2.0 giới thiệu phương thức

nặc danh (anonymous method) cho phộp ta khi khởi tạo đối tượng

delegate, khụng cần tỏch riờng phương thức mà delegate tham chiếu đến như vớ dụ sau:

// Khai bỏo delegate

public delegate void SimpleDelegate(int x);

// Khởi tạo delegate sử dụng phương thức nặc danh

SimpleDelegate simpleDelegate = delegate(int n) {

Console.WriteLine("Phương thức được gọi bởi delegate"); Console.WriteLine(n);

};

// Gọi delegate

simpleDelegate(2);

Biểu thức Lambda (Lambda expression): C# 3.0 đưa ra khỏi niệm

biểu thức lambda (lambda expression). Biểu thức lambda là một thao

tỏc nặc danh (anonymous function) chứa biểu thức hay khối lệnh, cú

thể sử dụng để tạo delegate hay cõy biểu thức (expression tree). Biểu

thức lambda sử dụng phộp toỏn lambda =>. Vế trỏi phộp toỏn lambda

là cỏc tham đối đầu vào và vế phải là biểu thức hay khối lệnh: (DanhSỏchThamĐối) => BiểuThức/ KhốiLệnh

Nếu khụng cú tham đối thỡ cỳ phỏp sẽ như sau:

() => BiểuThức/ KhốiLệnh

Biểu thức lambda: x => x * x cú thể được gỏn đến một đối tượng delegate như sau:

// Khai bỏo delegate

public delegate int SimpleDelegate(int x); // Khởi tạo delegate sử dụng biểu thức lambda SimpleDelegate simpleDelegate = x => x * x; // Gọi delegate

int y = simpleDelegate(2); Console.WriteLine(y);

Hay biểu thức lambda chứa khối lệnh cú thể gỏn đến đối tượng delegate như sau:

// Khai bỏo delegate

public delegate void SimpleDelegate(int x, int y); // Khởi tạo delegate sử dụng biểu thức lambda SimpleDelegate simpleDelegate = (x, y) => { Console.WriteLine(x); Console.WriteLine(y); }; // Gọi delegate simpleDelegate(2,3); 3.5. SỰ KIỆN (EVENT)

C# hỗ trợ lập trỡnh sự kiện bằng cỏch bổ sung khỏi niệm sự kiện

Một eventlà một thành viờn của lớp, cho phộp một lớp khai bỏo

sự kiện xảy ra khi chạy chương trỡnh, và xỏc định một delegate sẽ được gọi khi xảy ra sự kiện. Delegate cú thể cú một hay nhiều phương thức kết hợp sẽ được gọi khi sự kiện phỏt sinh. Nhiều sự kiện

cú thể chia sẻ cựng một delegate.

Cỏc bước để tạo một sự kiện trong C# là khai bỏo một sự kiện

(event declaration), đăng ký sự kiện (event accessor) và phỏt sinh sự

kiện (event raise).

Khai bỏo event: Để khai bỏo event trong một lớp, đầu tiờn phải

khai bỏo một kiểu delegate tham chiếu đến phương thức được gọi khi

sự kiện phỏt sinh.

Vớ dụ:

public delegate void Handler();

Kế tiếp ta khai bỏo event, một event được khai bỏo giống như

một biến kiểu delegate, ngoại trừ việc bổ sung từ khúa event, event thường khai bỏo public, nhưng cú thể sử dụng cỏc điều khiển truy

cập khỏc:

[BổTừ] event KiểuDelegate TờnSựKiện;

 Bổ từ (Modifier) là tựy chọn, cú thể là new, virtual, override, abstract, sealed, static, extern.

 Kiểu delegate (Delegate type) là kiểu delegate được gọi khi

phỏt sinh sự kiện.

Vớ dụ:

public event Handler WokenUp;

Đăng ký event: Mó đăng ký event để thờm hay xúa delegate từ

một event. Đăng ký event cú thể thực hiện khi kết hợp và xúa một

delegate vào event, sử dụng toỏn tử += và -=.

TờnSựKiện += new KiểuDelegate(TờnPhươngThức);

TờnSựKiện -= new KiểuDelegate(TờnPhươngThức); Tờn phương thức: Là phương thức mà delegate tham chiếu đến

Vớ dụ:

private void HandleEvent(object sender, EventArgs e) {

Console.WriteLine("Your animal has woken up. Feed it now!"); }

WokenUp += new Handler(HandleEvent);

Khi đó gọi sự kiện, xúa delegate khỏi event bằng cỏch sử dụng

toỏn tử -=.

WokenUp -= new Handler(HandleEvent);

Phỏt sinh một event: Khi đó khai bỏo event, cú thể sử dụng event như là một biến của kiểu delegate. Phỏt sinh một event như gọi

một delegate

TờnSựKiện(DanhSỏchThamĐối)

Danh sỏch tham đối là tham đối của phương thức mà delegate tham chiếu đến.

Vớ dụ: if (WokenUp != null) WokenUp(); Vớ dụ: using System; using System.Threading; namespace ConsoleApplication1 {

//Khai bỏo kiểu delegate

public delegate void Handler(); public class Animal

{

//Khai bỏo event

public event Handler WokenUp; public void Sleep()

{

Thread.Sleep(3000); // Phỏt sinh event

if (WokenUp != null) WokenUp(); }

}

public class Farmer {

public Farmer() {

//Thờm delegate vào event Animal a = new Animal();

a.WokenUp += new Handler(HandleEvent); a.Sleep();

}

private void HandleEvent() {

Console.WriteLine("Your animal has woken up. Feed it now!"); }

public static void Main() {

Console.WriteLine("Begin execution"); Farmer f = new Farmer();

Console.WriteLine("End execution"); Console.ReadKey(); } } } 3.6. CHỈ MỤC (INDEXER)

Một indexer là một thành viờn của lớp cho phộp một đối tượng

của một lớp hay struct được chỉ số như là một mảng. Cỏc thành phần

của mảng được truy cập sử dụng dấu ngoặc vuụng. Khai bỏo indexer giống như thuộc tớnh, ngoại trừ khi cỏc phương thức truy cập và thiết

lập cú tham đối. Một indexer được khai bỏo như sau:

[BổTừ] Kiểuthis [DanhSỏchThamĐối] {

//Mó kết hợp với indexer

Trong đú:

 Bổ từ là tựy chọn, và phải là điều khiển truy cập hay một

trong cỏc từ khúa new, virtual, sealed, override, hay abstract.  Kiểu (Return type) là kiểu dữ liệu trả về của indexer

 Danh sỏch tham đối (Parameter list) của indexer. Ít nhất phải

cú một tham đối truyền cho indexer. Tham đối khai bỏo ref và out là khụng được phộp

 Mó kết hợp với indexer tương tự cỏc phương thức truy cập và thiết lập sử dụng cho thuộc tớnh

Vớ dụ: using System; namespace ConsoleApplication1 { class SampleCollection<T> { // Khai bỏo một mảng

private T[] arr = new T[100];

// Định nghĩa Indexer, cho phộp đối tượng của lớp hiện hành sử

// dụng []

public T this[int i] {

get {

//Indexer này đơn giản trả về phần tử của mảng

return arr[i]; } set { arr[i] = value; } } } class Program {

static void Main(string[] args) {

SampleCollection<string> stringCollection = new SampleCollection<string>();

stringCollection[0] = "Hello, World";

System.Console.WriteLine(stringCollection[0]); }

} }

3.7. KIỂU CẤU TRÚC (STRUCT)

Cấu trỳc là một kiểu giỏ trị, được sử dụng để đúng gúi tập hợp cỏc đặc tớnh liờn quan. Tương tự định nghĩa lớp, cấu trỳc chứa biến

thành viờn, thuộc tớnh và phương thức, tham chiếu phương thức, sự

kiện và chỉ mục. Cấu trỳc giỳp bạn tổ chức dữ liệu khoa học hơn, mó

được trong sỏng dễ hiểu hơn và cải tiến tốc độ chương trỡnh và bộ nhớ

sử dụng.

Cấu trỳc là kiểu giỏ trị, trong khi lớp là kiểu tham chiếu. Cấu

trỳc khụng cú phương thức hủy, nhưng lớp cú thể cú phương thức

hủy. Một điểm khỏc nhau nữa giữa cấu trỳc và lớp là cấu trỳc khụng

thể kế thừa, nhưng cú thể cài đặt giao tiếp như lớp. Vỡ vậy, cỏc thành viờn của cấu trỳc khụng thể khai bỏo protected.

Nếu cú khụng nhiều thành viờn, hay chỉ cú thuộc tớnh trong cấu

trỳc và khụng kế thừa hay đa hỡnh, bạn nờn sử dụng kiểu cấu trỳc thay

cho kiểu lớp.

Cấu trỳc cũng cú phương thức khởi tạo, nhưng cấu trỳc khụng

thể định nghĩa một phương thức khởi tạo mà khụng cú tham đối. Cấu trỳc định nghĩa cỏc phương thức khởi tạo với cỏc tham đối chớnh xỏc như tất cả cỏc biến thành viờn.

Giống lớp, phương thức khởi tạo mặc định khởi tạo tất cả cỏc

thuộc tớnh về giỏ trị rỗng, nguyờn là 0, thực là 0.0, boolean là false, ký tự là ‘\0’, và kiểu tham chiếu là null.

Cỳ phỏp định nghĩa và sử dụng cấu trỳc tương tự lớp.

Vớ dụ: using System; struct Rectangle {

int width; public int Width {

get { return width;} set { width = value; } }

int height; public int Height {

get { return height; } set { height = value; } }

public Rectangle(int width, int height) {

this.width = width; this.height = height; }

public int Area() {

return this.width * this.height; }

}

class StructExample {

static void Main() {

Rectangle rect1 = new Rectangle(); rect1.Width = 1;

rect1.Height = 3;

Console.WriteLine("rect1: {0}, {1}", rect1.Width, rect1.Height); Rectangle rect2 = new Rectangle(5, 7);

Console.WriteLine("rect2: {0}, {1}", rect2.Width, rect2.Height); Console.WriteLine("Area of rect2: {0}", rect2.Area());

Console.ReadKey(); }

3.8. KIỂU TỔNG QUÁT (GENERIC TYPE)

C# 2.0 hỗ trợ lập trỡnh kiểu tổng quỏt với lớp, cấu trỳc, giao

tiếp, tham chiếu phương thức và phương thức.

Tham đối kiểu tổng quỏt cho phộp bạn định nghĩa lớp, cấu trỳc,

giao tiếp, tham chiếu phương thức hay phương thức sử dụng kiểu

tổng quỏt bất kỳ, sẽ được chỉ rừ kiểu khi bạn khởi tạo lớp, cấu trỳc,

hay sử dụng phương thức. Lập trỡnh kiểu tổng quỏt hỗ trợ tớnh tỏi sử

dụng cao, tiết kiệm thời gian cụng sức lập trỡnh, mà độ hoàn thiện của

Một phần của tài liệu Giáo trình lập trình windowns form với c net tập 1 TS lê trung hiếu, ths nguyễn thị minh thi (Trang 133)

Tải bản đầy đủ (PDF)

(179 trang)