1. Trang chủ
  2. » Giáo án - Bài giảng

bài giảng lập trình hướng đối tượng c

80 201 2

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 80
Dung lượng 1,53 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

bài giảng dành cho sinh viên các trường đại học cao đẳng ,khoa điện trên cả nước. Bài giảng do đội ngũ giảng viên trường đại học giao thông vận tải hà nội biên soạn , bài giảng bao gồm 7 chương , mỗi chương đều được trình bài cụ thể từ lý thuyết đến ví dụ , chưa bao gồm bài tập. các chương được trình bày dễ hiểu nhằm giúp người đọc hiểu rõ vấn đề nhất.

Trang 1

CHƯƠNG I: TỔNG QUAN VỀ LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG

1 Các kỹ thuật lập trình

1.1 Lập trình tuyến tính

Cách tiếp cận cơ bản của lập trình tuyến tính là lối tư duy tuần tự Các câu lệnh của chương trình được thực hiện tuần tự từ đầu tới cuối theo trình tự xuất hiện, lệnh này kế tiếp lệnh kia cho tới khi kết thúc chương trình

Các chương trình máy tính đầu tiên được lập trình bằng mã nhị phân, sử dụng các công tắc

cơ khí để nạp chương trình Sau đó chương trình và dữ liệu dưới dạng nhị phân được thể hiện bằng việc có hay không xuất hiện các lỗ được đục trên một tấm bìa (punched card) tại các vị trí định trước

Hình (I.1) Chương trình máy tính trên bìa đục lỗ

Sau này, khi yêu cầu xử lý dữ liệu lớn hơn, chương trình máy tính phức tạp hơn, nhiều câu lệnh hơn, việc sử dụng các bit nhị phân tỏ ra rất hạn chế Vì vậy để lập trình người ta sử dụng các câu lệnh gần với tiếng Anh gọi là ngôn ngữ lập trình sau đó chương trình dịch sẽ dịch các câu lệnh này sang ngôn ngữ máy để thực thi Các ngôn ngữ lập trình đầu tiên được thiết kế để lập các chương trình làm các công việc tương đối đơn giản như tính toán Phần lớn các chương trình cũng tương đối ngắn

Trang 2

Ngôn ngữ lập trình tuyến tính không có khả năng kiểm soát phạm vi nhìn thấy của các dữ liệu Mọi dữ liệu trong chương trình đều là dữ liệu toàn cục nghĩa là chúng có thể bị sửa đổi

ở bất kỳ phần nào của chương trình Việc dò tìm các thay đổi không mong muốn đó của các phần tử dữ liệu trong một dãy mã lệnh dài và vòng vèo đã từng làm cho các lập trình viên rất mất thời gian

Về bản chất, chương trình chia nhỏ thành các chương trình con riêng rẽ (còn gọi là hàm hay thủ tục) thực hiện các công việc rời rạc trong quá trình lớn hơn, phức tạp hơn Các hàm này được giữ càng độc lập với nhau càng nhiều càng tốt, mỗi hàm có dữ liệu và logic riêng Thông tin được chuyển giao giữa các hàm thông qua các tham số, các hàm có thể có các biến cục bộ mà bên ngoài phạm vi của hàm không thể truy xuất được chúng Như vậy, các hàm có thể được xem là các chương trình con được đặt chung với nhau để xây dựng nên một ứng dụng

Một khái niệm lớn đã được đưa ra trong lập trình có cấu trúc là sự trừu tượng hóa (Abstraction) Sự trừu tượng hóa có thể xem như khả năng quan sát một sự việc mà không

cần xem xét đến các chi tiết bên trong của nó Trong một chương trình có cấu trúc, chúng ta chỉ cần biết một hàm đã cho có thể làm được một công việc cụ thể gì là đủ Còn làm thế nào

mà công việc đó lại thực hiện được là không quan trọng, chừng nào hàm còn tin cậy được thì còn có thể dùng nó mà không cần phải biết nó thực hiện đúng đắn chức năng của mình như

thế nào Điều này gọi là sự trừu tượng hóa theo chức năng (Functional abstraction) và là

nền tảng của lập trình có cấu trúc

Các ngôn ngữ lập trình cấu trúc phổ biến là Pascal, C và C++ Riêng C++ ngoài việc có đặc trưng của lập trình cấu trúc do kế thừa từ C, còn có đặc trưng của lập trình hướng đối tượng Cho nên C++ còn được gọi là ngôn ngữ lập trình nửa cấu trúc, nửa hướng đối tượng

Đặc trưng

Đặc trưng cơ bản nhất của lập trình cấu trúc thể hiện ở mối quan hệ:

Chương trình = Cấu trúc dữ liệu + Giải thuật

Trong đó:

 Cấu trúc dữ liệu là cách tổ chức dữ liệu, cách mô tả bài toán dưới dạng ngôn ngữ lập trình

Trang 3

 Giải thuật là một quy trình để thực hiện một công việc xác định

Trong chương trình, giải thuật có quan hệ phụ thuộc vào cấu trúc dữ liệu:

 Một cấu trúc dữ liệu chỉ phù hợp với một số hạn chế các giải thuật

 Nếu thay đổi cấu trúc dữ liệu thì phải thay đổi giải thuật cho phù hợp

 Một giải thuật thường phải đi kèm với một cấu trúc dữ liệu nhất định

 Các ngôn ngữ lập trình cấu trúc cung cấp một số cấu trúc lệnh điều khiển chương trình

Ưu điểm

 Chương trình sáng sủa, dễ hiểu, dễ theo dõi

 Tư duy giải thuật rõ ràng

Nhược điểm

 Lập trình cấu trúc không hỗ trợ việc sử dụng lại mã nguồn: Giải thuật luôn phụ thuộc chặt chẽ vào cấu trúc dữ liệu, do đó, khi thay đổi cấu trúc dữ liệu, phải thay đổi giải thuật, nghĩa là phải viết lại chương trình

 Không phù hợp với các phần mềm lớn: tư duy cấu trúc với các giải thuật chỉ phù hợp với các bài toán nhỏ, nằm trong phạm vi một modul của chương trình Với dự

án phần mềm lớn, lập trình cấu trúc tỏ ra không hiệu quả trong việc giải quyết mối quan hệ vĩ mô giữa các modul của phần mềm

2 Lập trình hướng đối tượng

Xuất phát từ hai hạn chế chính của phương pháp lập trình cấu trúc:

 Không quản lí được sự thay đổi dữ liệu khi có nhiều chương trình cùng thay đổi một biến chung Vấn đề này đặc biệt nghiêm trọng khi các ứng dụng ngày càng lớn, người ta không thể kiểm soát được sự truy nhập đến các biến dữ liệu chung 8

 Không tiết kiệm được tài nguyên con người: Giải thuật gắn liền với cấu trúc dữ liệu, nếu thay đổi cấu trúc dữ liệu, sẽ phải thay đổi giải thuật, và do đó, phải viết lại mã chương trình từ đầu

Để khắc phục được hai hạn chế này khi giải quyết các bài toán lớn, người ta xây dựng một

Trang 4

phương pháp tiếp cận mới, là phương pháp lập trình hướng đối tượng, với hai mục đích chính:

 Đóng gói dữ liệu để hạn chế sự truy nhập tự do vào dữ liệu, không quản lí được

 Cho phép sử dụng lại mã nguồn, hạn chế việc phải viết lại mã từ đầu cho các chương trình

Việc đóng gói dữ liệu được thực hiện theo phương pháp trừu tượng hoá đối tượng thành lớp

từ thấp lên cao như sau:

 Thu thập các thuộc tính của mỗi đối tượng, gắn các thuộc tính vào đối tượng tương ứng

 Nhóm các đối tượng có các thuộc tính tương tự nhau thành nhóm, loại bỏ bớt các thuộc tính cá biệt, chỉ giữ lại các thuộc tính chung nhất Đây được gọi là quá trình trừu tượng hoá đối tượng thành lớp

 Đóng gói dữ liệu của các đối tượng vào lớp tương ứng Mỗi thuộc tính của đối tượng trở thành một thuộc tính của lớp tương ứng

 Việc truy nhập dữ liệu được thực hiện thông qua các phương thức được trang bị cho lớp Không được truy nhập tự do trực tiếp đến dữ liệu

 Khi có thay đổi trong dữ liệu của đối tượng, ta chỉ cần thay đổi các phương thức truy nhập thuộc tính của lớp, mà không cần phải thay đổi mã nguồn của các chương trình

 Trong lớp dẫn xuất (lớp được kế thừa) có thể sử dụng lại các phương thức của lớp

cơ sở (lớp bị lớp khác kế thừa) mà không cần thiết phải cài đặt lại mã nguồn

 Ngay cả khi lớp dẫn xuất định nghĩa lại các phương thức cho mình, lớp cơ sở cũng không bị ảnh hưởng và không phải sửa lại bất kì một đoạn mã nguồn nào

Ngôn ngữ lập trình hướng đối tượng phổ biến hiện nay là Java và C++ Tuy nhiên, C++ mặc

dù cũng có những đặc trưng cơ bản của lập trình hướng đối tượng nhưng vẫn không phải là ngôn ngữ lập trình thuần hướng đối tượng Java thật sự là một ngôn ngữ lập trình thuần hướng đối tượng

Đặc trƣng

Lập trình hướng đối tượng có hai đặc trưng cơ bản:

 Đóng gói dữ liệu: dữ liệu luôn được tổ chức thành các thuộc tính của lớp đối tượng Việc truy nhập đến dữ liệu phải thông qua các phương thức của đối tượng lớp

Trang 5

 Sử dụng lại mã nguồn: việc sử dụng lại mã nguồn được thể hiện thông qua cơ chế kế thừa Cơ chế này cho phép các lớp đối tượng có thể kế thừa từ các lớp đối tượng khác Khi đó, trong các lớp kế thừa, có thể sử dụng các phương thức (mã nguồn) của các lớp bị kế thừa, mà không cần phải định nghĩa lại

Trong lập trình hướng đối tượng chúng ta có:

Đối tượng = Phương thức + Dữ liệu

Ưu điểm

Lập trình hướng đối tượng có một số ưu điểm nổi bật:

 Không còn nguy cơ dữ liệu bị thay đổi tự do trong chương trình Vì dữ liệu đã được đóng gói vào các đối tượng Nếu muốn truy nhập vào dữ liệu phải thông qua các phương thức cho phép của đối tượng

 Khi thay đổi cấu trúc dữ liệu của một đối tượng, không cần thay đổi các đổi mã nguồn của các đối tượng khác, mà chỉ cần thay đổi một số hàm thành phần của đối tượng bị thay đổi Điều này hạn chế sự ảnh hưởng xấu của việc thay đổi dữ liệu đến các đối tượng khác trong chương trình

 Có thể sử dụng lại mã nguồn, tiết kiệm tài nguyên Vì nguyên tắc kế thừa cho phép các lớp kế thừa sử dụng các phương thức được kế thừa từ lớp khác như những phương thức của chính nó, mà không cần thiết phải định nghĩa lại

 Phù hợp với các dự án phần mềm lớn, phức tạp

3 Lập trình hướng đối tượng bằng ngôn ngữ C#

Thông thường, để mô tả đầy đủ các kỹ thuật trong lập trình hướng đối tượng, người ta thường sử dụng ngôn ngữ lập trình Java – một ngôn ngữ lập trình thuần hướng đối tượng hoặc C++

Tuy nhiên, với hai mục tiêu được đặt ra: một là dễ dàng tiếp cận, cũng như giảm đáng kể thời gian tìm hiểu các kỹ thuật lập trình hướng đối tượng cơ bản để phát triển các ứng dụng trên hệ điều hành windows, hai là sử dụng thành thạo bộ công cụ phát triển Visual Studio.net ứng dụng trong lĩnh vực điện điện tử nên tác giả sử dụng ngôn ngữ lập trình C# để trình bày các kỹ thuật trong lập trình hướng đối tượng với các lý do sau

C# là ngôn ngữ đơn giản: C# loại bỏ một vài sự phức tạp và rối rắm của những ngôn ngữ

như Java và c++, bao gồm việc loại bỏ những macro, những template, đa kế thừa, và lớp cơ

sở ảo (virtual base class) Chúng là những nguyên nhân gây ra sự nhầm lẫn hay dẫn đến những vấn đề cho các người phát triển

C# là ngôn ngữ hiện đại: Điều gì làm cho một ngôn ngữ hiện đại? Những đặc tính như là

xử lý ngoại lệ, thu gom bộ nhớ tự động, những kiểu dữ liệu mở rộng, và bảo mật mã nguồn

Trang 6

là những đặc tính được mong đợi trong một ngôn ngữ hiện đại C# chứa tất cả những đặc tính trên

C# là ngôn ngữ hướng đối tượng: Những đặc điểm chính của ngôn ngữ hướng đối tượng

(Object-oriented language) là sự đóng gói (encapsulation), sự kế thừa (inheritance), và đa hình (polymorphism) C# hỗ trợ tất cả các đặc tính trên

C# là ngôn ngữ mạnh mẽ và cũng mềm dẻo: C# được sử dụng cho nhiều các dự án khác

nhau như là tạo ra ứng dụng xử lý văn bản, ứng dụng đồ họa, bản tính…

Trang 7

CHƯƠNG II: C# CƠ BẢN

1 Ứng dụng Console

Ứng dụng console giao tiếp với người dùng thông qua bàn phím và không có giao diện người dùng (UI), giống như các ứng dụng thường thấy trong Windows Bước đầu để tìm hiểu các kỹ thuật trong lập trình hướng đối tượng và dùng ngôn ngữ C# để mô tả các kỹ thuật này ta viết các ứng dụng console

Tiếp đó ta sẽ tìm hiểu và sử dụng các thư viện để xây dựng các ứng dụng có giao diện đồ họa trên Windows Nội dung này sẽ được trình bày trong chương VII

Ví dụ (II.1) Tạo dự án C# console đầu tiên

Bước 1: Mở Visual Studio

Bước 2: Chọn menu File->New->Project để tạo một dự án console based với tên „First_prg‟

và tên Solution là Session01 như Hình (II.1)

Hình (II.1) Cửa sổ tạo dự án mới

Bước 3: Đổi tên lớp file class „program.cs„ thành „First_prg.cs‟

Bước 4: Chèn mã vào file „First_prg.cs‟ như bên dưới

Trang 8

Bước 5: Chọn File -> Save

Bước 6: Chọn Build -> Build First_prg để dịch dự án

Bước 7: Chọn Debug -> Start without Debuging để chạy chương trình

Màn hình hiển thị của chương trình như sau

Hình (II.2) Màn hình hiển thị Ví dụ (II.1)

2 Biến và hằng

Khai báo và gán giá trị cho biến: <kiểu> <tên biến> = <giá trị>;

Khai báo và gán giá trị cho hằng: const <kiểu> <tên hằng> = <giá trị>;

tên biến và hằng phải tuân theo các quy tắc sau:

 Chỉ bắt đầu bằng một kí tự (chữ), hoặc một dấu gạch dưới , hoặc một kí tự dollar

 Không có khoảng trắng giữa tên

 Từ kí tự thứ hai, có thể dùng các kí tự (chữ), chữ số, dấu dollar, dấu gạch dưới

 Không trùng với các từ khoá

 Phân biệt chữ hoa chữ thường

3 Kiểu dữ liệu

C# phân tập hợp kiểu dữ liệu này thành hai loại: Kiểu dữ liệu giá trị (value) và kiểu dữ liệu tham chiếu (reference) Đối với một kiểu dữ liệu giá trị thì sẽ được lưu giữ kích thước thật trong bộ nhớ đã cấp phát là stack Trong khi đó thì địa chỉ của kiểu dữ liệu tham chiếu thì được lưu trong stack nhưng đối tượng thật sự thì lưu trong bộ nhớ heap

Kiểu dữ liệu Số byte Mô tả

byte 1 Số nguyên không dấu giá trị từ 0 255

Trang 9

char 2 Ký tự Unicode

bool 1 Giá trị logic true/false

sbyte 1 Số nguyên có dấu giá trị từ-128 127

short 2 Số nguyên có dấu giá trị từ -32768 32767

ushort 2 Số nguyên không dấu giá trị từ 0 65536

int 4 Số nguyên có dấu giá trị từ 2,147,483,648 2,147,483,647

uint 4 Số nguyên không dấu giá trị từ 0 4,294,967,295

long 8 Số nguyên có dấu giá trị từ

-9,223,372,036,854,775,808 9,223,372,036,854,775,807ulong 8 Số nguyên không dấu giá trị từ 0 18,446,744,073,709,551,615float 4 Kiểu só thực dấu phẩy động giá trị từ

-3.402823e38 3.402823e38double 8 Kiểu số thực dấu phẩy động có độ chính xác gấp đôi float giá trị từ

-1.79769313486232e308 1.79769313486232e308decimal 8 Giá trị thập phân có độ chính xác tới 28 chữ số, được dùng trong

tính toán tài chính, kiểu này đòi hỏi phải có hậu tố m hoặc M theo sau giá trị

Bảng (II.1) Các kiểu dữ liệu trong C#

Khi khai báo biến mà chưa khởi tạo giá trị cho các biến thì chúng nhận giá trị ngầm định

Kiểu dữ liệu Giá trị ngầm định

byte, int, long… (kiểu số) 0

Ví dụ (II.2) sử dụng các kiểu dữ liệu (datatype)

Bước 1: Thêm một dự án console với tên là „DataType‟ vào solution hiện hành Hình (II.3) Bước 2: click chuột phải vào project DataTypes -> set as Startup project

Trang 10

Bước 3: đổi tên file class „Program.cs‟ thành „DataTypes.cs‟

Hình (II.3) Các bước thêm một dự án mới vào solution hiện hành

Bước 4: Sửa mã lệnh trong file „DataTypes.cs‟ như sau

Console.WriteLine( "{0} is an integer value" , intVal);

Console.WriteLine( "{0} is an double value" , dblVal);

Console.WriteLine( "{0} is an string" , strVal);

Console.ReadLine();

}

}

Bước 5: Chọn menu File -> Save để lưu trữ file chương trình nguồn

Bước 6: Chọn Build -> Build „DataTypes‟ để build dự án

Bước 7: Chọn Debug -> Start without Debuging để chạy chương trình

Trang 11

Hình (II.4) Màn hình hiển thị Ví dụ (II.2)

Trên Bảng (II.1) trình bày các kiểu dữ liệu đơn, được xây dựng sẵn (Built-in datatypes) trong ngôn ngữ lập trình C# Ngoài ra ta có thể xây dựng các kiểu dữ liệu phức hợp từ các kiểu dữ liệu đơn này gọi là các kiểu dữ liệu do người dùng định nghĩa (User-defined datatypes) như kiểu liệt kê (enum), cấu trúc (struct), mảng (array), lớp (class)

Một kiểu dữ liệu do người dùng định nghĩa đầu tiên là kiểu liệt kê Kiểu liệt kê bao gồm một

tập các giá trị hằng cho trước, được định nghĩa bằng tử khóa enum

Ví dụ (II.3) Kiểu liệt kê:

Bước 1: Thêm một dự án console với tên là „EnumType‟ vào solution hiện hành

Bước 2: click chuột phải vào project EnumType -> set as Startup project

Bước 3: đổi tên file class „Program.cs‟ thành „EnumType.cs‟

Bước 4: Sửa mã lệnh trong file „EnumType.cs‟ như sau

Console.WriteLine( "Nhiet do dong: {0}" , NhietDoNuoc.DoDong);

Console.WriteLine( "Nhiet do nguoi:{0}" , NhietDoNuoc.DoNguoi);

Console.WriteLine( "Nhiet do am: {0}" , NhietDoNuoc.DoAm);

Console.WriteLine( "Nhiet do nong: {0}" , NhietDoNuoc.DoNong);

Console.WriteLine( "Nhiet do soi: {0}" , NhietDoNuoc.DoSoi);

Console.ReadLine();

}

}

Bước 5: Chọn menu File -> Save để lưu trữ file chương trình nguồn

Bước 6: Dịch và chạy chương trình

Trang 12

Hình (II.5) Màn hình hiển thị Ví dụ (II.3)

Trang 13

trả về vào toán hạng bên trái Ví dụ c -= a tương đương với c = c - a

*= Nhân và gán

Nhân các giá trị của toán hạng bên trái với toán toán hạng bên phải và gán giá trị trả về vào toán hạng bên trái Ví dụ c *= a tương đương với c = c*a

/= Chia và gán

Chia giá trị của toán hạng bên trái cho toán toán hạng bên phải và gán giá trị trả

về vào toán hạng bên trái Ví dụ c /= a tương đương với c = c/a

%= Lấy số dư và gán

Chia giá trị của toán hạng bên trái cho toán toán hạng bên phải và gán giá trị số

dƣ vào toán hạng bên trái Ví dụ c %= a tương đương với c = c%a

Bảng (II.3) Các toán tử số học 4.2 Toán tử Bit

Các toán tử dạng bit cho phép ta thao tác trên từng bit riêng biệt trong các kiểu dữ liệu nguyên thuỷ

Toán tử Mô tả

~ Phủ định bit (NOT)

Trả về giá trị phủ định của một bít

& Toán tử AND bít

Trả về giá trị là 1 nếu các toán hạng là 1 và 0 trong các trường hợp khác

Chuyển toàn bộ các bít cuả một số sang phải một vị trí, giữ nguyên dấu của số

âm Toán hạng bên trái là số bị dịch còn số bên phải chỉ số vị trí mà các bít cần dịch

Trang 14

Trả về một giá trị “Đúng” (True) nếu chỉ khi cả hai toán tử có giá trị “True” Toán

tử này kiểm tra sự tương đương của hai toán hạng

! Toán hạng đơn tử NOT

Chuyển giá trị từ True sang False và ngược lại

Bảng (II.6) Các toán tử logic

Trang 15

4.5 Toán tử điều kiện

Toán tử điều kiện là một loại toán tử đặc biệt vì nó bao gồm ba thành phần cấu thành biểu thức điều kiện Cú pháp:

<biểu thức 1> ? <biểu thức 2> : <biểu thức 3>;

 <biểu thức 1>: Biểu thức logic Trả trả về giá trị True hoặc False

 <biểu thức 2>: Là giá trị trả về nếu <biểu thức 1> xác định là True

 <biểu thức 3>: Là giá trị trả về nếu <biểu thức 1> xác định là False

4.6 Toán tử gán

Toán tử gán (=) dùng để gán một giá trị vào một biến và có thể gán nhiều giá trị cho nhiều

biến cùng một lúc Ví dụ đoạn lệnh sau gán một giá trị cho biến var và giá trị này lại được

gán cho nhiều biến trên một dòng lệnh đơn

int var = 20;

int p,q,r,s;

p=q=r=s=var;

Dòng lệnh cuối cùng được thực hiện từ phải qua trái Đầu tiên giá trị ở biến var được gán

cho s, sau đó giá trị của s được gán cho r và cứ tiếp như vậy

4.7 Thứ tự ƣu tiên của các toán tử

Các biểu thức được viết ra nói chung gồm nhiều toán tử Thứ tự ưu tiên quyết định trật tự thực hiện các toán tử trên các biểu thức Bảng dưới đây liệt kê thứ tự thực hiện các toán tử trong C#

Thứ tự Toán tử

1 Các toán tử đơn như +, -, ++,

2 Các toán tử số học và các toán tử dịch như *, /, +, -, <<, >>

3 Các toán tử quan hệ như >, <, >=, <=, = =, !=

4 Các toán tử logic và Bit như &&, ||, &, |, ^

5 Các toán tử gán như =, *=, /=, +=, -=

Bảng (II.7) Thứ tự ƣu tiên các phép toán 4.8 Thay đổi thứ tự ƣu tiên

Để thay đổi thứ tự ưu tiên trên một biểu thức, bạn có thể sử dụng dấu ngoặc đơn ():

 Phần được giới hạn trong ngoặc đơn được thực hiện trước

 Nếu dùng nhiều ngoặc đơn lồng nhau thì toán tử nằm trong ngoặc đơn phía trong sẽ thực thi trước, sau đó đến các vòng phía ngoài

 Trong phạm vi một cặp ngoặc đơn thì quy tắc thứ tự ưu tiên vẫn giữ nguyên tác dụng

Trang 17

thư viện Mỗi lớp có một tên riêng, vì vậy FCL có hàng ngàn tên như ArrayList, Dictionary, FileSelector,…

Điều này làm nảy sinh vấn đề, người lập trình không thể nào nhớ hết được tên của các lớp trong NET Framework Tệ hơn nữa là sau này có thể ta tạo lại một lớp trùng với lớp đa có chẳng hạn Ví dụ trong quá trình phát triển một ứng dụng ta cần xây dựng một lớp từ điển và lấy tên là Dictionary, và điều này dẫn đến sự tranh chấp khi biên dịch vì C# chỉ cho phép một tên duy nhất

Chắc chắn rằng khi đó chúng ta phải đổi tên của lớp từ điển mà ta vừa tạo thành một cái tên khác chẳng hạn như myDictionary Khi đó sẽ làm cho việc phát triển các ứng dụng trở nên phức tạp, cồng kềnh Đến một sự phát triển nhất định nào đó thì chính là cơn ác mộng cho nhà phát triển

Giải pháp để giải quyết vấn đề này là việc tạo ra một namespace, namsespace sẽ hạn chế

phạm vi của một tên, làm cho tên này chỉ có ý nghĩa trong vùng đa định nghĩa

Giả sử có một người nói Tùng là một kỹ sư, từ kỹ sư phải đi kèm với một lĩnh vực nhất định nào đó, vì nếu không thì chúng ta sẽ không biết được là anh ta là kỹ sư cầu đường, cơ khí hay phần mềm Khi đó một lập trình viên C# sẽ bảo rằng Tùng là CauDuong.KySu phân biệt với CoKhi.KySu hay PhanMem.KySu

Namespace trong trường hợp này là CauDuong, CoKhi, PhanMem sẽ hạn chế phạm vi của những từ theo sau Nó tạo ra một vùng không gian để tên sau đó có nghĩa Tương tự như vậy

ta cứ tạo các namespace để phân thành các vùng cho các lớp trùng tên không tranh chấp với nhau

C# đưa ra từ khóa using đề khai báo sử dụng namespace trong chương trình:

using <Tên namespace>

Để tạo một namespace dùng cú pháp sau:

namespace <Tên namespace>

Trang 18

theo kiểu ngôn ngữ C và kết hợp với định nghĩa lớp do đó thể hiện của mảng có thể truy cập những phương thức và thuộc tính của System.Array

7.1 Khai báo mảng

Chúng ta có thể khai báo một mảng trong C# với cú pháp theo sau:

<kiểu dữ liệu>[] <tên mảng>

Ví dụ:

int[] myIntArray;

Cặp dấu ngoặc vuông ([]) báo cho trình biên dịch biết rằng chúng ta đang khai báo một mảng Kiểu dữ liệu là kiểu của các thành phần chứa bên trong mảng Trong ví dụ bên trên,

myIntArray được khai báo là mảng số nguyên Chúng ta tạo thể hiện của mảng bằng cách

sử dụng từ khóa new như sau:

myIntArray = new int[5];

Khai báo này sẽ thiết lập bên trong bộ nhớ một mảng chứa năm số nguyên với giá trị ngầm định bằng 0 (xem Bảng (II.2) Giá trị ngầm định)

7.3 Khởi tạo thành phần của mảng

Chúng ta có thể khởi tạo nội dung của một mảng ngay lúc tạo thể hiện của mảng bằng cách đặt những giá trị bên trong dấu ngoặc ({}) C# cung cấp hai cú pháp để khởi tạo các thành phần của mảng, một cú pháp dài và một cú pháp ngắn:

int[] myIntArray = new int[5] { 2, 4, 6, 8, 10};

int[] myIntArray = { 2, 4, 6, 8, 10};

Không có sự khác biệt giữa hai cú pháp trên, và hầu hết các chương trình đều sử dụng cú pháp ngắn

Ví dụ (II.4) Khai báo và sử dụng mảng

Bước 1: Thêm một dự án console với tên là „BasedArray‟ vào solution hiện hành

Bước 2: click chuột phải vào project BasedArray -> set as Startup project

Bước 3: Sửa mã lệnh trong file „Program.cs‟ như sau

class Program

{

static void Main(string[] args)

Trang 19

Bước 4: Chọn menu File -> Save để lưu trữ file chương trình nguồn

Bước 5: Dịch và chạy chương trình

Hình (II.6) Màn hình hiển thị Ví dụ (II.4) 7.4 Các phương thức và thuộc tính của mảng

Mảng là đối tượng thuộc lớp System.Array đã được xây dựng sẵn bao gồm các phương thức

và thuộc tính hay dùng sau

trị trong mảng một chiều Reverse() Phương thức tĩnh public đảo thứ tự của các thành phần trong mảng một

chiều Sort() Phương thức tĩnh public sắp xếp giá trị trong mảng một chiều

IsFixedSize Thuộc tính public giá trị bool thể hiện mảng có kích thước cố định hay

không

IsReadOnly Thuộc tính public giá trị bool thể hiện mảng chỉ đọc hay không

IsSynchronized Thuộc tính public giá trị bool thể hiện mảng có hỗ trợ thread-safe

Trang 20

Length Thuộc tính public chiều dài của mảng

Rank Thuộc tính public chứa số chiều của mảng

SynRoot Thuộc tính public chứa đối tượng dùng để đồng bộ truy cập trong

mảng GetEnumerator() Phương thức public trả về IEnumerator

GetLength() Phương thức public trả về kích thước của một chiều cố định

trong mảng GetLowerBound() Phương thức public trả về cận dưới của chiều xác định trong

mảng GetUpperBound() Phương thức public trả về cận trên của chiều xác định trong mảng Initialize() Khởi tạo tất cả giá trị trong mảng kiểu giá trị bằng cách gọi bộ khởi

Mảng hai chiều được tổ chức thành các dòng và cột, trong đó các dòng là được tính theo hàng ngang của mảng, và các cột được tính theo hàng dọc của mảng

Mảng ba chiều cũng có thể được tạo ra nhưng thường ít sử dụng do khó hình dung Những phần tử thuộc mảng ba chiều bây giờ là các mảng hai chiều

Ngôn ngữ C# hỗ trợ hai kiểu mảng đa chiều là:

 Mảng đa chiều cùng kích thước: trong mảng này mỗi dòng trong mảng có cùng kích thước với nhau Mảng này có thể là hai hay nhiều hơn hai chiều

 Mảng đa chiều không cùng kích thước: trong mảng này các dòng có thể không cùng kích thước với nhau

Mảng đa chiều cùng kích thước

Mảng đa chiều cùng kích thước còn gọi là mảng hình chữ nhật (rectanguler array) Trong mảng hai chiều cổ điển, chiều đầu tiên được tính bằng số dòng của mảng và chiều thứ hai được tính bằng số cột của mảng

Để khai báo mảng hai chiều, chúng ta có thể sử dụng cú pháp theo sau:

Trang 21

<kiểu dữ liệu> [,] <tên mảng>

Ví dụ để khai báo một mảng hai chiều có tên là myRectangularArray để chứa hai dòng và ba cột các số nguyên, chúng ta có thể viết như sau:

int [ , ] myRectangularArray;

Ví dụ (II.5) Mảng hai chiều cùng kích thước

Ví dụ này minh họa việc khai báo, tạo mới, khởi tạo và in nội dung ra của một mảng hai

chiều ra màn hình Trong đó, vòng lặp for được sử dụng để khởi tạo các thành phần trong

mảng

Bước 1: Thêm một dự án console với tên là „SameSizeArrays‟ vào solution hiện hành

Bước 2: click chuột phải vào project SameSizeArrays -> set as Startup project

Bước 3: Sửa mã lệnh trong file „Program.cs‟ như sau

class Program

{

static void Main(string[] args)

{

const int rows = 4;

const int columns = 3;

int [,] rectangularArray = new int[rows, columns];

// khởi tạo các thành phần trong mảng

for(int i = 0; i < rows; i++)

// xuất nội dung ra màn hình

for(int i = 0; i < rows; i++)

}

Console.ReadLine();

}

}

Bước 4: Chọn menu File -> Save để lưu trữ file chương trình nguồn

Bước 5: Dịch và chạy chương trình

Trang 22

Hình (II.7) Màn hình hiển thị Ví dụ (II.5)

Trong Ví dụ (II.5) chúng ta thực hiện việc khởi tạo giá trị cho các phần tử bằng vòng lặp for

Ngoài ra, ta cũng có thể trực tiếp khi tạo các phần tử của mảng theo cú pháp:

Mảng đa chiều có kích khác nhau

Cũng như giới thiệu trước kích thước của các chiều có thể không bằng nhau, điều này khác với mảng đa chiều cùng kích thước Nếu hình dạng của mảng đa chiều cùng kích thước có dạng hình chữ nhật thì hình dạng của mảng này không phải hình chữ nhật vì các chiều của chúng không điều nhau

Khi chúng ta tạo một mảng đa chiều kích thước khác nhau thì chúng ta khai báo số dòng trong mảng trước Sau đó với mỗi dòng sẽ giữ một mảng, có kích thước bất kỳ Những mảng này được khai báo riêng Sau đó chúng ta khởi tạo giá trị các thành phần trong những mảng bên trong Trong mảng này, mỗi chiều là một mảng một chiều Để khai báo mảng đa chiều

có kích thước khác nhau ta sử dụng cú pháp sau, khi đó số ngoặc chỉ ra số chiều của mảng:

Trang 23

Ví dụ (II.6) Mảng đa chiều khác kích thước

Ví dụ này tạo ra mảng khác kích thước tên myJaggedArray, khởi tạo các thành phần, rồi sau

đó in ra màn hình Để tiết kiệm thời gian, chúng ta sử dụng mảng các số nguyên để các thành phần của nó được tự động gán giá trị mặc định Và ta chỉ cần gán một số giá trị cần thiết

Bước 1: Thêm một dự án console với tên là „DiffSizeArrays‟ vào solution hiện hành

Bước 2: click chuột phải vào project DiffSizeArrays -> set as Startup project

Bước 3: Sửa mã lệnh trong file „Program.cs‟ như sau

class Program

{

static void Main(string[] args)

{

const int rows = 4;

int[][] jaggedArray = new int[rows][];

jaggedArray[3] = new int[5];

Trang 24

Bước 4: Chọn menu File -> Save để lưu trữ file chương trình nguồn

Bước 5: Dịch và chạy chương trình

Hình (II.8) Màn hình hiển thị Ví dụ (II.6)

8 Định dạng hiển thị trong chế độ dòng lệnh (console)

8.1 Định dạng hiển thị số

Ví dụ (II.7)

Bước 1: Thêm dự án console „NumberFormat‟ vào solution

Bước 2: Thiết lập dự án này là mặc đinh bằng cách click phải lên dự án NumberFormat -> set as Startup project

Bước 3: Đổi tên lớp „Program.cs‟ thành „NumberFormat.cs‟

Bước 4: Chèn mã lệnh bên dưới vào „NumberFormat.cs‟

/*This program demonstrates the the numeric formatting in C#*/

Console.WriteLine( "Exponential formatting - {0:E}" , 888.8);

Console.WriteLine( "Fixed-point formatting - {0:F3}" , 888.8888);

Console.WriteLine( "General formatting - {0:G}" , 888.8888);

Console.WriteLine( "Number formatting - {0:N}" , 8888888.8);

Trang 25

Console.WriteLine( "Hexadecimal formatting - {0:X4}" , 88);

}

}

Bước 5: Chọn menu File -> Save để lưu

Bước 6: Dịch và chạy chương trình

Hình (II.9) Màn hình hiển thị Ví dụ (II.7) 8.2 Định dạng hiển thị ngày giờ

Ví dụ (II.8)

Bước 1: Thêm dự án console „DateTimeFormat‟ vào solution

Bước 2: Thiết lập dự án này là mặc đinh bằng cách click phải lên dự án DateTimeFormat -> set as Startup project

Bước 3: Đổi tên lớp „Program.cs‟ thành „DateTimeFormat.cs‟

Bước 4: Chèn mã lệnh sau vào file „DateTimeFormat.cs‟

Trang 26

Console.WriteLine("u format: {0:u}", dt);

Console.WriteLine("U format: {0:U}", dt);

Console.WriteLine("y format: {0:y}", dt);

Console.WriteLine("Y format: {0:Y}", dt);

}

}

Bước 5: Chọn menu File -> Save để lưu

Bước 6: Dịch và chạy chương trình

Hình (II.10) Màn hình hiển thị Ví dụ (II.8)

Trang 27

CHƯƠNG III: LỚP VÀ ĐỐI TƯỢNG

1 Đối tượng

Trong lập trình hướng đối tượng, người ta mô hình hóa tất cả các thực thể cần thiết trong hệ thống thành một khái niệm gọi là đối tượng Các đối tượng được sinh ra, và hoạt động trong quá trình chương trình đang chạy Mỗi đối tượng có các trạng thái (state) và các hành vi (method, action, behavior) Các đối tượng này có thể thực hiện các hành vi trên dữ liệu của mình (state) và tướng tác với các đối tượng khác để giải quyết yêu cầu của bài toán

Ví dụ:

Trong bài toán quản lí buôn bán xe hơi của một cửa hàng kinh doanh, mỗi chiếc xe đang có mặt trong cửa hàng được coi là một đối tượng Chẳng hạn, một chiếc xe nhãn hiệu “Ford”, màu trắng, giá 5000$ là một đối tượng

Một đối tượng là một thực thể đang tồn tại trong hệ thống và được xác định bằng ba yếu tố:

 Định danh đối tượng: xác định duy nhất cho mỗi đối tượng trong hệ thống, nhằm phân biệt các đối tượng với nhau

 Trạng thái của đối tượng: là sự tổ hợp của các giá trị của các thuộc tính mà đối tượng đang có

 Hoạt động của đối tượng: là các hành động mà đối tượng có khả năng thực hiện được

Ví dụ một chiếc xe trong cửa hàng có:

Để biểu diễn đối tượng trong lập trình hướng đối tượng, người ta trừu tượng hoá đối tượng

để tạo nên khái niệm lớp đối tượng

2 Lớp

Nếu như đối tượng là một thực thể cụ thể, tồn tại trong hệ thống có trạng thái và hành vi cụ thể thì lớp là một khái niệm trừu tượng, dùng để chỉ một tập hợp các đối tượng có cùng một cấu trúc (có cùng tập thuộc tính và hành vi)

Ví dụ:

Trang 28

Trong bài toán quản lí buôn bán xe hơi của một cửa hàng kinh doanh, mỗi chiếc xe đang có mặt trong cửa hàng được coi là một đối tượng Nhưng khái niệm “Xe hơi” là một lớp đối tượng dùng để chỉ tất cả các loại xe hơi của của hàng

 Thuộc tính của lớp xác định cấu trúc về trạng thái của các đối tượng thuộc lớp (thành phần dữ liệu của đối tượng thuộc lớp)

 Phương thức của lớp xác định hành động của các đối tượng thuộc lớp (thành phần hành động của đối tượng thuộc lớp)

Ví dụ, lớp xe ô tô được mô tả bằng các thuộc tính và phương thức sau:

//khai báo biến thành phần

//khai báo phương thức

}

2.2 Khai báo biến thành phần của lớp

Biến thành phần của lớp được khai báo theo cú pháp:

<tính chất> <kiểu dữ liệu> <tên biến thành phần>;

<Kiểu dữ liệu>: có thể là các kiểu dữ liệu cơ bản sẵn, có thể là các lớp do người dùng tự định nghĩa

<Tên biến thành phần>: được đặt tên theo quy tắc đặt tên biến

Trang 29

<Tính chất>: Các biến thành phần và phương thức của lớp có các tính chất được đặc trưng bởi các từ khóa

 public: có thể được truy cập từ bên ngoài lớp định nghĩa

 protected: chỉ được truy cập từ lớp định nghĩa và các lớp kế thừa từ lớp đó

 private: chỉ được truy cập trong phạm vi bản thân lớp định nghĩa

 internal: chỉ được truy cập bởi những phương thức của bất cứ lớp trong cùng khối hợp ngữ

 static: chỉ định cho cách thành phần thuộc lớp, có thể được truy cập trực tiếp bằng

<tên lớp>.<tên biến thành phần> mà không cần khởi tạo một đối tượng của lớp Nếu không chỉ rõ từ khóa định nghĩa <tính chất> thì ngầm định mức truy xuất của thành

phần sẽ là private

2.3 Khai báo phương thức của lớp

Phương thức của lớp được khai báo theo cú pháp

<tính chất> <kiểu trả về> <tên phương thức> ([<các tham số>])

{

}

Tính chất: đặc trưng bởi các từ khoá tương tự như tính chất của biến thành phần Giá trị

mặc định là private

Kiểu trả về: Kiểu dữ liệu trả về của phương thức, có thể là kiểu dữ liệu sẵn có của C# hoặc

là kiểu do người dùng tự định nghĩa

Tên phương thức: tuân theo qui tắc đặt tên biến

Các tham số: các tham số của phương thức, được liệt kê theo cặp <kiểu tham số> <tên tham

số>, các tham số được phân biệt bởi dấu phẩy

Ví dụ (III.1) Tạo lớp Car

Bước 1: Mở Visual Studio

Bước 2: Chọn menu File->New->Project để tạo một dự án console based với tên „CarDemo‟

và tên Solution là Session_III

Bước 3: Trong cửa sổ Solution Explorer, click chuột phải vào Project CarDemo chọn

Add->Class, nhập tên class là Car.cs, sau đó chèn class Car như bên dưới

using System;

class Car

{

// khai bao thuoc tinh

public string model;

public string color;

public int yearBuilt;

// khai bao phuong thuc

public void Start()

Trang 30

<tên lớp> <tên đối tượng> = new <tên lớp>();

Ví dụ, muốn tạo một đối tượng có kiểu là lớp Car, ta dùng lệnh sau:

Car myCar = new Car();

Ví dụ (III.2) Tạo lớp Program

Bước 4: (tiếp ví dụ CarDemo) Chèn mã lệnh sau vào lớp Program như sau

// Tạo ra 1 đối tượng thuộc lớp Car và gán địa chỉ vào myCar

System.Console.WriteLine( "Creating a Car object and assigning " + "its memory location to myCar" );

myCar = new Car();

// Gán giá trị cho các trường của myCar

myCar.model = "MR2" ;

myCar.color = "black" ;

myCar.yearBuilt = 1995;

// Hiển thị giá trị các trường của myCar

System.Console.WriteLine( "myCar details:" );

System.Console.WriteLine( "myCar.model=" +myCar.model);

System.Console.WriteLine( "myCar.color = " +myCar.color);

System.Console.WriteLine( "myCar.yearBuilt=" +myCar.yearBuilt);

// Gọi các phương thức của myCar

Trang 31

Hình (III.1) Màn hình hiển thị Ví dụ (III.2)

3 Một số kỹ thuật trong xây dựng lớp

3.1 Phương thức khởi tạo của lớp

Phương thức khởi tạo (Constructor) được dùng để khởi tạo một đối tượng lớp, nghĩa là gán các giá trị khởi đầu cho các biến thành phần (nếu có), và tạo ra một đối tượng cụ thể Phương thức khởi tạo phải cùng tên với lớp Cú pháp định nghĩa phương thức khởi tạo như sau

public <tên lớp>([<các tham số>])

{

//các lệnh khởi tạo đối tượng

}

Lưu ý:

 Phương thức khởi tạo phải có tên trùng với tên của lớp

 Phương thức khởi tạo không có giá trị trả về

 Phương thức khởi tạo có tính chất public

 Có thể có nhiều phương thức khởi tạo của cùng một lớp

Biến this là một biến ẩn đặc biệt luôn tồn tại: một lớp có đúng một biến ẩn this Biến này được sử dụng trong khi chạy và nó trỏ đến bản thân lớp chứa nó Biến this thường được sử

dụng trong các hàm khởi tạo của lớp

Ví dụ (III.3) Lớp Car có thêm phương thức khởi tạo

using System;

class Car

{

// khai bao thuoc tinh

public string model;

public string color;

public int yearBuilt;

// phuong thuc khoi tao

public Car()

{

Trang 32

model = "" ;

color = "" ;

yearBuilt = 0;

}

// khai bao phuong thuc

public void Start()

 Phương thức hủy bỏ không có tham số và không có chỉ định tính chất phương thức

 Phương thức hủy bỏ được bộ gom rác gọi để giải phóng bộ nhớ và xóa bỏ đối tượng, sau đó đối tượng không còn tồn tại và không thể được tham chiếu lại

 Phương thức hủy bỏ không thể nạp chồng và không được kế thừa

 Phương thức hủy bỏ không thể được gọi tường minh như các phương thức bình thường Nó chỉ được tự động gọi bởi bộ gom rác khi xóa bỏ đối tượng

3.3 Truyền tham số cho phương thức

Khi định nghĩa phương thức của lớp thực hiện tính toán xử lý các dữ liệu đầu vào để đưa ra kết quả thì ta cần khai báo các tham số cho phương thức Thông thường các tham số của phương thức mô tả dữ liệu đầu vào cho quá trình tính toán trong phương thức Khi khai báo phương thức, nếu phương thức có tham số thì tham số được khai báo trong cặp dấu () sau tên phương thức với cú pháp

… <Tên phương thức> (<Kiểu dữ liệu> <Tên tham số>)

Ví dụ: khai báo một phương thức trả về bình phương một số

public int squareInt (int value)

Nếu có nhiều tham số thì các tham số được khai báo cách nhau dấu phẩy

… <Tên phương thức> (<Kiểu dữ liệu> <Tên tham số1>, <Kiểu dữ liệu> <Tên tham số2>…)

Trang 33

Ví dụ: khai báo một phương thức trả về tổng của hai số

public int sumInt(int value1, int value2)

Khi định nghĩa phương thức, các tham số được khai báo chỉ có ý nghĩa hình thức Nghĩa là chỉ định rằng phương thức sẽ được sử dụng với định dạng như khi khai báo Ví dụ phần khai bao phương thức squareInt ở trên chỉ ra rằng phương thức sẽ nhận một giá trị kiểu int làm đầu vào rồi tính toán ra bình phương của số đó và trả về làm kết quả của quá trình tính toán Chỉ đến khi phương thức được gọi (call) thực thi thật sự thì tham số mới được truyền bằng giá trị hoặc bằng biến thật sự Có hai cơ chế truyền tham số đó là: Truyền tham trị và truyền tham biến Sau đây ta sẽ tìm hiểu chi tiết về hai cơ chế truyền tham số này

số mà không ảnh hưởng gì tới tham số thật sự Đây là cơ chế truyền tham số ngầm định của C#

Truyền tham biến

Khác với cơ chế truyền tham trị, khi truyền biến hay đối tượng làm tham số của phương thức thì các lệnh trong thân phương thức làm việc trực tiếp với biến hay đối tượng được truyền vào (làm việc với vùng bộ nhớ dành chó chính biến hay đối tượng được truyền vào) Vì vậy, khi các lệnh làm thay đổi giá trị của biến hay đối tượng đó thì sự thay đổi đó vẫn được lưu lại khi phương thức kết thúc Để xác định tham số được truyền theo cơ chế này, khi khai báo

tham số ta sử dụng từ khóa ref hoặc out

Ví dụ (III.4) Truyền tham số bằng tham trị hay tham biến

Bước 1: Thêm một dự án console với tên Parameters vào solution Session_III

Bước 2: Thiết lập Parameters là dự án mặc định bằng cách click chuột phải vào project Parameters -> set as Startup project

Bước 3: Chèn mã lệnh vào lớp Program như sau

Trang 34

arg = 4;

squareVal(arg);

Console.WriteLine(arg); //Hiển thị giá trị arg vẫn là 4

// Truyền tham biến

// Giá trị của biến arg bị thay đổi.

//Khai báo phương thức có tham số truyền tham trị (ngầm định)

static void squareVal(int valParameter)

Bước 4: Dịch và chạy chương trình

Hình (III.2) Màn hình hiển thị Ví dụ (III.4)

Trong Ví dụ (III.4) phương thức squareVal có tham số valParameter được khai báo truyền theo cơ chế tham trị (ngầm định) Trong phương thức Main() biến arg được truyền vào làm tham số cho phương thức squareVal qua lời gọi squareVal(arg); Khi đó, trong thân phương thức squareVal sẽ tạo ra một vùng bộ nhớ bản sao và sao chép giá trị của biến arg vào đó Các lệnh trong thân phương thức squareVal chỉ tác động lên vùng bộ nhớ bản sao này mà không làm ảnh hưởng gì tới biến arg Đó là lý do giá trị của biến arg vẫn không thay

đổi và bằng 4

Còn trong phương thức squareRef tham số refParameter được khai báo với từ khóa ref nghĩa là truyền tham biến Trong phương thức Main() biến arg được truyền vào làm tham số cho phương thức squareRef qua lời gọi squareRef(ref arg); Khi đó, các lệnh trong thân phương thức squareRef sẽ làm việc trực tiếp với vùng bộ nhớ lưu trữ biến arg, đọc giá trị

trong vùng bộ nhớ này, tính bình phương giá trị đó và ghi đè giá trị này lên giá trị cũ Đó lày

lý do giá trị của biến arg bị thay đổi thành bình phương của nó

Trang 35

Chúng ta có thể dùng out thay thế cho từ khóa ref với ý nghĩa gần như nhau nghĩa là tham

số được truyền bằng tham biến, chỉ khác nếu dùng từ khóa ref thì biến được truyền vào làm

tham số phải được gán giá trị khởi tạo trước khi truyền vào làm tham số cho phương thức

Từ khóa out thường được sử dụng khi ta muốn xây dựng các phương thức trả về nhiều hơn

một giá trị

3.4 Nạp chồng phương thức

Trong một lớp, cho phép ta định nghĩa nhiều phương thức có cùng tên nhưng khác nhau về

số các tham số hoặc kiểu của các tham số, các phương thức như vậy gọi là các phương thức được nạp chồng (overloading)

Ví dụ (III.5) Nạp chồng phương thức khởi tạo

Bước 1: Thêm một dự án console với tên CarOverloading vào solution Session_III

Bước 2: Thêm class Car vào dự án và chèn mã lệnh như bên dưới

using System;

class Car

{

// khai bao thuoc tinh

public string model;

public string color;

public int yearBuilt;

// phuong thuc khoi tao

// khai bao phuong thuc

public void Start()

Tương tự như phương thức khởi tạo, các phương thức khác cũng có thể nạp chồng bằng cách

sử dụng cùng một tên phương thức nhưng số tham số và kiểu tham số có thể khác nhau Bước 3: Chèn mã dưới vào lớp Program, dịch và chạy thử

Trang 36

// Tạo ra 1 đối tượng thuộc lớp Car và gán địa chỉ vào myCar

System.Console.WriteLine( "Creating a Car object and assigning " + "its memory location to myCar" );

myCar = new Car();

// Gán giá trị cho các trường của myCar

myCar.model = "MR2" ;

myCar.color = "black" ;

myCar.yearBuilt = 1995;

// Hiển thị giá trị các trường của myCar

System.Console.WriteLine( "myCar details:" );

System.Console.WriteLine( "myCar.model=" +myCar.model);

System.Console.WriteLine( "myCar.color = " +myCar.color);

System.Console.WriteLine( "myCar.yearBuilt=" +myCar.yearBuilt);

// Gọi các phương thức của myCar

myCar.Start();

myCar.Stop();

// Khai báo và tạo ra một đối tượng khác thuộc lớp Car

System.Console.WriteLine( "Creating another Car objectand"+"assigning its memory location to redPorsche" );

//gọi hàm tạo có tham số của lớp Car để tạo ra đối tượng Car mới

Car redPorsche = new Car(“Boxster”, “red”, 2012);

System.Console.WriteLine( "redPorsche is a " + redPorsche.model);

//Gán đối tượng myCar bằng redPorsche

System.Console.WriteLine( "Assigning redPorsche to myCar" );

myCar = redPorsche;

System.Console.WriteLine( "myCar details:" );

System.Console.WriteLine( "myCar.model = " +myCar.model);

System.Console.WriteLine( "myCar.color = " +myCar.color);

System.Console.WriteLine( "myCar.yearBuilt = " +myCar.yearBuilt);

// gán giá trị null cho myCar nghĩa là xóa bỏ đối tượng myCar

Trang 37

Tính đóng gói thể hiện khi định nghĩa lớp, các thành phần của lớp được chỉ định phạm vi có thể truy xuất được (Access modifier) bởi các từ khóa public, private, protected… Có hai vấn

đề được đặt ra là:

Một là, đối với các thành phần public, ta có thể truy nhập, thay đổi giá trị từ bên ngoài bằng cách gán trực tiếp giá trị cho thành phần đó Vậy làm thế nào có thể kiểm soát được việc thay đổi giá trị cho thành phần đó có phù hợp hay không? Chẳng hạn, kiểm soát không cho phép gán năm sản xuất của chiếc xe nhận giá trị là một chuỗi ký tự

Hai là, làm thế nào từ bên ngoài có thể truy xuất được các thành phần riêng (private) của đối tượng?

Trong lý thuyết về lập trình hướng đối tượng nói cung cũng như trong các ngôn ngữ lập trình hướng đối tượng khác như Java hoặc C++ thường không có sự phân biệt giữa hai khái niệm biến thành phần (member variables) hay trường (fields) của lớp với thuộc tính (properties) của lớp, và để giải quyết hai vấn đề trên, khi xây dựng lớp thường định nghĩa các phương thức cho phép thiết lập (setter method) và truy xuất (getter method) thành phần

dữ liệu của lớp

Nhưng Trong C# đưa ra khái niệm thuộc tính (properties) của lớp, phân biệt với khái niệm biến thành phần (member variables) hay trường (fields) của lớp Thuộc tính cung cấp giao diện cho phép truy cập vào các biến thành phần của lớp thay vì truy cập trực tiếp Thông qua

đó, thuộc tính cung cấp khả năng bảo vệ các trường dữ liệu bên trong lớp bằng việc đọc ghi chúng thông qua thuộc tính Như vậy, có thể nói thuộc tính trong C# và các phương thức thiết lập và truy xuất trong các ngôn ngữ lập trình khác có cùng bản chất, chỉ khác nhau về

cú pháp thể hiện

Để khai báo thuộc tính, đầu tiên là khai báo tên thuộc tính để truy cập, tiếp theo là phần thân định nghĩa thuộc tính nằm trong cập dấu ({}) Bên trong thân của thuộc tính là khai báo hai

bộ truy xuất (get) và thiết lập (set) dữ liệu theo cú pháp:

<tính chất> <kiểu dữ liệu> <Tên thuộc tính>

Ví dụ (III.6) Thuộc tính của lớp

Bước 1: Vẫn trong solution Session_III, thêm một dự án mới tên là Properties

Bước 2: Thêm lớp Employer vào dự án và viết mã như bên dưới

Trang 38

class Employer

{

private string empName;

public string EmployerName

Employer empObj = new Employer();

empObj.EmployerName = "John Carter" ;

Console.WriteLine( "The name: " + empObj.EmployerName);

Bước 5: Dịch và chạy chương trình màn hình hiển thị như sau

Hình (III.3) Màn hình hiển thị Ví dụ (III.6)

Trong Ví dụ (III.6) khi định nghĩa lớp Employer đã định nghĩa thuộc tính EmployerName bao gồm bộ truy xuất (get) để đọc trường empName, bộ thiết lập (set) để ghi dữ liệu vào trường empName của lớp Trong hai bộ này có thể viết thêm các lệnh xử lý khác tuy theo yêu cầu được đặt ra chẳng hạn như kiểm soát giá trị thiết lập cho các trường của lớp

Bộ truy xuất dữ liệu (get accessor)

Phần khai báo bộ truy xuất dữ liệu tương tự như một phương thức của lớp dùng để trả về giá trị có kiểu dữ liệu chính là kiểu của biến thành phần cần truy xuất Trong ví dụ trên, bộ truy

Trang 39

xuất dữ liệu của thuộc tính EmployerName cũng tương tự như một phương thức trả về một giá trị chuỗi chính là giá trị của biến thành viên empName của đối tượng hiện thời:

Ví dụ:

Console.WriteLine( "The name: " + empObj.EmployerName);

Bộ truy xuất lấy dữ liệu thực hiện và giá trị của thuộc tính được trả về chính là giá trị của biến thành viên empName của đối tượng hiện thời

Bộ thiết lập dữ liệu (set accessor)

Bộ thiết lập dữ liệu sẽ thiết lập một giá trị mới cho biến thành phần và tương tự như một

phương thức không có giá trị trả về void Khi định nghĩa bộ thiết lập dữ lịêu chúng ta phải

sử dụng từ khóa value để đại diện cho tham số được truyền vào cho thuộc tính

Ví dụ:

empObj.EmployerName = "John Carter" ;

//value chính là “John Carter”

Trong trường hợp này bộ thiết lập thuộc tính thiết lập giá trị cho biến thành viên Ngoài ra,

ta có thể viết thêm các lệnh trong bộ thiết lập cho phép kiểm soát giá trị truyền vào cho thuộc tính có hợp quy cách hay không hoặc lưu trữ giá trị của thuộc tính vào cơ sở dữ liệu nếu cần thiết

Hai bộ truy xuất và thiết lập thuộc tính tạo nên 3 loại thuộc tính khác nhau Nếu thuộc tính chỉ được định nghĩa bộ truy xuất ta nói thuộc tính đó là thuộc tính chỉ đọc Nếu chỉ có bộ thiết lập ta nói đó là thuộc tính chỉ ghi Nếu thuộc tính có cả hai bộ truy xuất và thiết lập ta nói đó là bộ truy xuất đọc/ghi

Trang 40

Hình (III.4) Ba loại thuộc tính

Từ C# 3.0 trở đi cho phép định nghĩa thuộc tính ngắn gọn hơn Cách viết này gọi là định nghĩa thuộc tính tự động Trong Ví dụ (III.6) thay vì định nghĩa thuộc tính EmployerName tường minh như trên, ta có thể định nghĩa ngắn gọn như sau

4.2 Chỉ mục

Trong phần trên đã trình bày cách định nghĩa các thuộc tính cho phép đọc ghi giá trị của các biến thành phần của lớp Bên ngoài có thể đọc ghi các biến thành phần thông qua các thuộc tính này

Ta xem xét thêm một trường hợp nếu biến thành phần của lớp là một mảng hay tổng quát hơn là một tập hợp các phần tử cùng kiểu thì để đọc ghi giá trị cho từng phần tử ta phải xây dựng thuộc tính hoặc phương thức để đọc ghi giá trị cho từng phần tử Để đơn giản hóa việc này và cung cấp một cách thức cho phép đọc ghi giá trị cho từng phần tử này giống như đọc ghi giá trị cho từng phần tử của mảng C# đưa ra khái niệm chỉ mục (indexer)

Cú pháp khai báo chỉ mục trong lớp như sau:

<kiểu trả về> this [<kiểu tham số> <tham số>]

{

//định nghĩa bộ truy xuất(get;)

//định nghĩa bộ thiết lập (set;)

}

Trong đó <kiểu trả về> được quyết định bởi kiểu của biến thành phần được trả về bởi chỉ mục, <tham số> thường là chỉ số của phần tử trong biến thành phần mà chỉ mục tham chiếu

Ngày đăng: 17/05/2015, 14:26

HÌNH ẢNH LIÊN QUAN

Hình (V.9) Sơ đồ các loại ngoai lệ thừa kế từ Exception - bài giảng lập trình hướng đối tượng c
nh (V.9) Sơ đồ các loại ngoai lệ thừa kế từ Exception (Trang 66)

TỪ KHÓA LIÊN QUAN

TRÍCH ĐOẠN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w