Tong Hop C#
C# là một ngôn ngữ mang những đặc điểm của C++, có phong cách lập trình như Java và có mô hình ứng dụng như Basic. Nếu đã biết về C++ thì các bạn sẽ mất không dưới một giờ để tìm hiểu cú pháp của C#. Còn nếu các bạn đã quen thuộc với Java thì sẽ là một lợi thế khác khi học C#. Cấu trúc chương trình Java, khái niệm về gói (package), garbage collection … chắc chắn sẽ giúp bạn học C# nhanh hơn. Trong bài viết này, khi chúng ta nói về các cấu trúc của C#, tôi sẽ xem như các bạn đã biết C++.
Bài viết này sẽ nói về các cấu trúc và những đặc điểm của ngôn ngữ C#, minh họa bằng những ví dụ ngắn gọn và dễ hiểu để khi các bạn nhìn vào ví dụ, các bạn có thể hiểu rõ những khái niệm. Trong bài viết này , chúng ta sẽ bàn về những chủ đề sau:
·Cấu trúc chương trình
·Namespaces
·Kiểu dữ liệu
·Biến
·Toán tử và biểu thức
·Kiểu liệt kê
·Câu lệnh
·Class và Struct
·Modifier
·Các thuộc tính (Property)
·Interface
·Các thông số hàm
·Mảng (array)
·Indexer
·Boxing và Unboxing
·Delegate
·Thừa kế và tính đa hình
Chúng ta sẽ không bàn về các vấn đề như: C# thông dụng hơn hay C++ thông dụng hơn, các khái niệm garbage collection, threading, xử lý file … chuyển kiểu dữ liệu, thư viện .Net.
Cấu trúc chương trình
Cũng như C++, C# thuộc dạng case – sensitive (phân biệt chữ hoa và chữ thường). Dấu chấm phẩy ( là ký hiệu ngăn cách các phát biểu. Không như C++, trong C# không có sự phân chia giữa phần khai báo (header) và phần hiện thực (cpp). Mọi đoạn mã (khai báo class và hiện thực) đều được đặt trong một file có phần mở rộng .cs. Bây giờ chúng ta làm quen với chương trình đầu tiên của C#, chương trình Hello world:
using System;
namespace MyNameSpace
{
{
class HelloWorld
{
static void Main(string[] args)
{
Console.WriteLine (“Hello World”);
}
}
Trong C#, tất cả các câu lệnh, phương thức… được “gói” trong một class, và tất cả các class được “gói” trong một namespace (giống như file trong folder). Cũng như C++, có một chương trình chính chứa những điểm nhập cho chương trình của bạn. Chương trình chính của C++ được bắt đầu bằng “main”, trong khi đó chương trình chính của C# bắt đầu với “Main”.
Không cần đặt dấu chấm phẩy sau một khối class hay sau định nghĩa struct. Đó là quy định của C++, C# thì không cần.
Namespaces
Mỗi class được gói lại trong một namespace. Thật ra, namespaces là một khái niệm trong C++, nhưng trong C# chúng ta dùng namespaces thường xuyên hơn. Các bạn có thể truy xuất một class trong một namespaces bằng cách dùng dấu chấm (.). MyNameSpace là namespace của chương trình Hello world ở trên.
Bây giờ chúng ta hãy viết lại chương trình HelloWorld bằng cách truy xuất lớp HelloWorld từ một lớp khác trong một namespaces khác:
using System;
namespace AnotherNameSpace
{
class AnotherClass
{
public void Func()
{
Console.WriteLine (“Hello World”);
}
}
}
Bây giờ từ lớp HelloWorld, các bạn có thể truy xuất nó:
using System;
using AnotherNameSpace;
namespace MyNameSpace
{
class HelloWorld
{
static void Main(string[] args)
{
AnotherClass obj = new AnotherClass();
obj.Func();
}
}
}
Trong thư viện .Net, System là namespace cấp cao nhất trong các namespace. Trong C#, bằng cách mặc định tồn tại một namespace toàn cục, một class định nghĩa bên ngoài một namespace được lưu trực tiếp trong namespace toàn cục này và do đó bạn có thể truy xuất lớp này mà không cần bất kỳ một qualifier (bổ từ) nào. Bạn cũng có thể định nghĩa những namespace lồng nhau.
--Using
Chỉ thị #include trong C++ được thay thế bởi từ khóa using, theo sau đó là tên của một namespace, chẳng hạn như “using System”. System là một namespace nền trong đó chứa tất cả những namespace khác và tất cả các lớp được định nghĩa trong những namespace đó. Lớp nền cho mọi đối tượng là Object trong namespace System.
----Biến
Các biến trong C# hầu hết đều giống trong C++, ngoại trừ những khác biệt sau:
· Biến trong C# luôn cần phải khởi tạo trước khi bạn truy xuất nó, nếu không bạn sẽ bị báo lỗi trong khi biên dịch. Do đó, phải nhớ rằng không thể truy xuất một biến chưa được khởi tạo.
· Bạn không thể truy xuất một con trỏ không trỏ vào đâu cả trong C#.
· Một biểu thức không thể gọi một phần tử của mảng (array) mà chỉ số của nó vượt ra khỏi kích thước của mảng.
· Không có khái niệm biến toàn cục hay hàm toàn cục trong C# và những khái
niệm về toàn cục được biểu diễn thông qua những hàm và biến static
---Kiểu dữ liệu
Tất cả những kiểu dữ liệu của C# được định nghĩa trong lớp Object. Có hai loại kiểu dữ liệu:
*Kiểu dữ liệu cơ bản (dựng sẵn)
*Kiểu dữ liệu do người dùng định nghĩa
Dưới đây là bảng liệt kê các kiểu dữ liệu định sẵn trong trong C#:
Kiểu Kích thước Mô tả
Byte 1 unsigned byte
Sbyte 1 signed byte
Short 2 signed short
Ushort 2 unsigned short
Int 4 signed integer
Uint 4 unsigned integer
Long 8 signed long
Ulong 8 unsigned long
Float 4 floating point
Double 8 double precision
Decimal 8 fixed precision
String unicode string
Char unicode char
Bool true, false boolean
Ghi chú: Kích thước của các kiểu dữ liệu trong C++ và C# không giống nhau, ví dụ như kiểu long trong C++ là 4 byte , trong C# là 8 byte. Kiểu bool và string cũng khác nhau, kiểu bool trong C# chỉ chấp nhận giá trị true hay false chứ không chấp nhận giá trị integer. Kiểu dữ liệu do người dùng định nghĩa bao gồm:
1.Class
2.Struct
3.Interface
Nếu phân chia kiểu dữ liệu theo sự cấp phát bộ nhớ thì ta có thể chia làm hai loại:
1.Kiểu giá trị
2.Kiểu tham khảo
Kiểu giá trị
Kiểu giá trị là những dữ liệu được cấp phát bộ nhớ trong stack. Các loại dữ liệu này bao gồm:
·Tất cả những kiểu dữ liệu dựng sẵn ngoại trừ kiểu string.
·Struct
·Kiểu liệt kê
Kiểu tham khảo
Kiểu tham khảo được cấp phát bộ nhớ trên heap và sẽ trở thành rác khi chúng không được sử dụng nữa. Để khai báo kiểu dữ liệu này, ta dùng từ khóa new, và không như C++, không có từ khóa delete . Trong C#, chúng tự động được gom lại bởi “ bộ phận thu thập rác” (garbage collector).
--Kiểu tham khảo bao gồm:
·Class
·Interface
·Kiểu tập hợp như mảng
·String
--Kiểu liệt kê (Enumeration)
Kiểu liệt kê trong C# hoàn toàn giống như C++, chúng được định nghĩa thông qua từ khóa enum
Ví dụ như:
enum Weekdays
{
Saturday, Sunday, Monday
Tuesday, Wednesday, Thursday, Friday
}
Class và Struct
Class và Struct cũng tương tự như C++, ngoại trừ sự khác nhau về sự cấp phát bộ nhớ. Những đối tượng của class được cấp phát bộ nhớ trong heap và được tạo ra bằng cách dùng new, còn struct được cấp phát bộ nhớ trong stack. Struct trong C# là kiểu dữ liệu rất nhẹ và nhanh. Do đó đối với những kiểu dữ liệu nặng bạn nên khai báo class. Bây giờ chúng ta quan sát ví dụ sau:
struct Date
{
int day;
int month;
int year;
}
class Date
{
int day;
int month;
int year;
string weekday;
string monthName;
public int GetDay()
{
return day;
}
public int GetMonth()
{
return month;
}
public int GetYear()
{
return year;
}
public void SetDay(int Day)
{
day = Day ;
}
public void SetMonth(int Month)
{
month = Month;
}
public void SetYear(int Year)
{
year = Year;
}
public bool IsLeapYear()
{
return (year/4 == 0);
}
public void SetDate (int day, int month, int year)
{
}
...
}
Các thuộc tính
Nếu bạn đã quen thuộc với hướng đối tượng trong C++, bạn ắt hẳn phải có chút khái niệm gì đó về thuộc tính (properties). Các thuộc tính trong ví dụ class Date ở trên là day, month và year. Nếu trong C++, bạn phải dùng phương thức Get và Set thì C# cung cấp những cách thuận tiện hơn, đơn giản hơn và trực tiếp hơn để truy xuất những thuộc tính. Đối với ví dụ trên ta có thể viết lại như sau:
using System;
class Date
{
public int Day{
get {
return day;
}
set {
day = value;
}
}
int day;
public int Month{
get {
return month;
}
set {
month = value;
}
}
int month;
public int Year{
get {
return year;
}
set {
year = value;
}
}
int year;
public bool IsLeapYear(int year)
{
return year%4== 0 ? true:false;
}
public void SetDate (int day, int month, int year)
{
this.day = day;
this.month = month;
this.year = year;
}
}
Sau đây là cách bạn lấy và thiết lập thuộc tính:
class User
{
public static void Main()
{
Date date = new Date();
date.Day = 27;
date.Month = 6;
date.Year = 2003;
Console.WriteLine(“Date: {0}/{1}/{2}”,date.Day, date.Month, date.Year);
}
}
Bổ từ (Modifier)
Trong C++, chúng ta đã gặp các bổ từ thông dụng như public, private và protected. Sau đây chúng ta sẽ nói về một số bổ từ mới trong C#.
Readonly
readonly chỉ được dùng cho những dữ liệu thành viên (member) của class. Dữ liệu readonly chỉ có thể đọc được khi chúng đã được khởi tạo trực tiếp hay gán giá trị cho chúng trong constructor. Sự khác nhau giữa dữ liệu readonly và const (hằng) là khi khai báo hằng, ta phải khởi tạo giá trị cho nó một cách trực tiếp. Hãy nhìn vào ví
dụ sau:
class MyClass
{
//trực tiếp
const int constInt = 100;
//không trực tiếp
readonly int myInt = 5;
readonly int myInt2;
public MyClass()
{
// không trực tiếp
myInt2 = 8;
}
public Func()
{
myInt = 7; //không hợp lệ
Console.WriteLine(myInt2.ToString());
}
}
Sealed
Sử dụng từ khóa sealed khi khai báo một class sẽ không cho phép bạn lấy bất kỳ class nào từ nó. Do đó bạn nên sử dung từ khóa sealed cho những lớp mà bạn không muốn những lớp con thừa kế chúng.
sealed class CanNotbeTheParent
{
int a = 5;
}
Unsafe
Bạn có thể định nghĩa một ngữ cảnh không an toàn trong C# bằng cách dùng từ khóa unsafe.
Trong ngữ cảnh không an toàn, bạn có thể viết một đoạn mã không an toàn, ví dụ như con trỏ C++ chẳng hạn. Chúng ta hãy xem xét ví dụ sau:
public unsafe MyFunction( int * pInt, double* pDouble)
{
int* pAnotherInt = new int;
*pAnotherInt = 10;
pInt = pAnotherInt;
...
*pDouble = 8.9;
}
Interface
Nếu bạn đã có khái niệm về COM, bạn sẽ dễ dàng hiểu được nội dung của phần này. Một interface là một lớp trừu tượng cơ bản, trong đó chỉ chứa những ký hiệu của hàm, sự hiện thực những hàm này được cung cấp bởi những lớp con. Trong C#, bạn có thể định nghĩa những class như những interface thông qua từ khóa interface. .NET có nền tảng từ nhiều interface. Trong C# bạn không thể dùng nhiều lớp thừa kế, điều mà trong C++ cho phép, nhưng thật ra bản chất của sự đa thừa kế được thực hiện thông qua interface. Những lớp con của bạn cũng có thể hiện thực đa interface.
using System;
interface myDrawing
{
int originx
{
}
int originy
{
}
void Draw(object shape);
}
class Shape: myDrawing
{
int OriX;
int OriY;
public int originx
{
get{
return OriX;
}
set{
OriX = value;
}
}
public int originy
{
get{
return OriY;
}
set{
OriY = value;
}
}
public void Draw(object shape)
{
...
}
public void MoveShape(int newX, int newY)
{
.....
}
}
---Mảng
Mảng trong C# có nhiều tính năng vượt trội hơn so với C++. Mảng được cấp phát bộ nhớ trong heap và do đó nó được truyền bằng tham khảo. Bạn không thể truy xuất một phần tử vượt ngoài giới hạn trong một mảng (có chỉ số lớn hơn số phần tử trong mảng). Do đó C# đã khắc phục lỗi này. Ngoài ra C# còn cung cấp một số hàm trợ giúp để xử lý các phần tử trong mảng. Ta có thể thấy rõ sự khác nhau giữa cú pháp của mảng trong C++ và C# là:
·Dấu ngoặc vuông được đặt sau tên kiểu chứ không phải sau tên biến.
·Bạn có thể tạo vùng nhớ cho phần tử trong mảng bằng cách dùng từ khóa new.
Ngoài ra C# còn hỗ trợ việc hiện thực mảng một chiều (single dimensional), đa chiều (multi dimensional) và jagged array (mảng của mảng). Ví dụ như:
// mảng một chiều đơn giản
int[] array = new int[10];
for (int i = 0;i < array.Length; i++)
array = i;
// mảng hai chiều
int[,] array2 = new int[5,10];
array2[1,2] = 5;
// mảng 3 chiều
int[,,] array3 = new int[5,10,5];
array3[0,2,4] = 9;
// mảng của mảng
int[][] arrayOfarray = = new int[2];
arrayOfarray[0] = new int[4];
arrayOfarray[0] = new int[] {1,2,15};
----Indexer
Indexer được dùng để viết một phương thức truy xuất trực tiếp một phần tử từ một tập hợp bằng cách dùng dấu [ ], như trong mảng. Việc bạn cần làm chỉ là chỉ rõ chỉ số để truy xuất một phần tử. Cú pháp của một indexer cũng giống như của thuộc tính một class, ngoại trừ chúng cần một thông số nhập, đó chính là chỉ số của phần tử cần truy xuất.
Bây giờ chúng ta tiếp tục tham khảo một ví dụ cho vấn đề này. Trong ví dụ sau bạn sẽ bắt gặp lớp CollectionBase, đó là một lớp thư viện dùng để tạo ra những tập hợp. Danh sách (list) là một protected member của lớp CollectionBase, trong đó lưu trữ tập hợp các danh sách.
class Shapes: CollectionBase
{
public void add(Shape shp)
{
List.Add(shp);
}
//indexer
public Shape this[int index]
{
get {
return (Shape) List[index];
}
set {
List[index] = value ;
}
}
}
Boxing/Unboxing
Boxing là một khái niệm mới trong C#. Như đã đề cập ở trên, mọi kiểu dữ liệu, dựng sẵn hay do người dùng định nghĩa, đều được lấy từ một lớp cơ bản là Object trong namespace System.
Do đó việc đóng gói những kiểu căn bản hay nguyên thủy vào trong class Object được gọi là boxing, và thao tác ngược lại được gọi là unboxing. Ví dụ như:
class Test
{
static void Main()
{
int myInt = 12;
// boxing
object obj = myInt ;
// unboxing
int myInt2 = (int) obj;
}
}
Ví dụ trên cho ta thấy cả hai thao tác boxing và unboxing. Một giá trị int có thể được chuyển đổi thành đối tượng và chuyển đổi trở lại thành int. Khi kiểu dữ liệu của một biến cần được chuyển thành một kiểu truyền bằng tham khảo, một object box được tạo ra để chứa giá trị, và giá trị được lưu vào box. Unboxing chỉ là quá trình ngược lại. Khi một object box được trả lại thành kiểu nguyên thủy , giá trị sẽ được chuyển từ box sang ô nhớ lưu trữ ban đầu.
---Thông số của hàm
Trong C# có 3 loại thông số:
1.Thông số in/ truyền bằng trị.
2.Thông số in– out/truyền bằng tham khảo.
3.Thông số out.
Nếu bạn đã nắm rõ về COM interface và những kiểu thông số của nó, bạn sẽ dễ dàng hiểu được các kiểu thông số của C#.
--Thông số in/ truyền bằng trị
Khái niệm thông số truyền bằng trị cũng tương tự như trong C++. Giá trị truyền được chép vào một ô nhớ và được truyền vào hàm.
Ví dụ:
SetDay(5);
...
void SetDay(int day)
{
....
}
---Thông số in – out/truyềnbằng tham khảo
Thông số truyền bằng tham khảo trong C++ được truyền thông qua một con trỏ hay toán tử &. Trong C#, thông số truyền bằng tham khảo còn được gọi là thông số in – out, vì khi bạn truyền một địa chỉ tham khảo của một ô nhớ, bạn đã truyền một giá trị nhập và lấy một giá trị xuất từ hàm đó.
Bạn không thể truyền một thông số chưa khởi tạo vào một hàm. C# dùng từ khóa ref để chỉ thông số truyền bằng tham khảo. Bạn cũng có thể dùng từ khóa ref cho một đối số trong khi truyền nó vào một hàm có thông số truyền bằng tham khảo. Ví dụ:
int a= 5;
FunctionA(ref a);
Console.WriteLine(a);
void FunctionA(ref int Val)
{
int x= Val;
Val = x* 4;
}
----Thông số out
Là thông số chỉ trả về giá trị là kết quả của một hàm, không đòi hỏi giá trị nhập. C# dùng từ khóa out cho loại tham số này.
int Val;
GetNodeValue(Val);
bool GetNodeValue(out int Val)
{
Val = value;
return true;
}
---Số lượng các thông số và mảng
Để truyền thông số là một mảng trong C#, người ta dùng từ khóa params. Chỉ có thể có một đối số kiểu mảng. Bạn có thể truyền phần tử như là một đối số của mảng đó. Tốt nhất, ta hãy xem ví dụ sau:
void Func(params int[] array)
{
Console.WriteLine(“number of elements {0}”, array.Length);
}
Func();
Func(5);
Func(7,9);
Func(new int[] {3,8,10});
int[] array = new int[8] {1,3,4,5,5,6,7,5};
Func(array);
---Toán tử và biểu thức
Hầu hết các toán tử trong C# hoàn toàn giống như trong C++, do đó biểu thức cũng vậy. Tuy nhiên C# còn bổ sung thêm một số toán tử mới và hữu ích. Chúng ta sẽ xem xét vài toán tử trong số đó.
---Toán tử is
Toán tử này được dùng để kiểm tra xem kiểu của các toán hạng có tương đương hay không. Toán tử is thường được sử dụng trong kịch bản đa ngữ cảnh. Toán tử này có hai toán hạng và kết quả trả về có kiểu bool. Chúng ta xem ví dụ sau:
void function(object param)
{
if(param is ClassA)
// something
else if(param is MyStruct)
//something
}
}
---Toán tử as
Toán tử as kiểm tra xem kiểu của các toán hạng có khả đổi hay không, nếu có thì kết quả trả về là một đối tượng đã được chuyển đổi hay được box. Nếu đối tượng không chuyển đổi hay box được, kết quả trả về null. Chúng ta xem ví dụ sau để hiểu rõ hơn về khái niệm này:
Shape shp = new Shape();
//kết quả là null, không chuyển đổi
//kiểu được
Vehicle veh = shp as Vehicle;
Circle cir = new Circle();
Shape shp = cir;
//sẽ được chuyển đổi
Circle cir2 = shp as Circle;
object[] objects = new object[2];
objects[0] = “Aisha”;
object[1] = new Shape();
for(int i=0; i&< objects.Length; i++)
{
str = objects as string;
if(str == null)
Console.WriteLine(“can not be converted”);
else
Console.WriteLine(“{0}”,str);
}
----Câu lệnh
Đa số các câu lệnh trong C# đều tương tự như trong C++, ngoài ra còn có một số câu lệnh mới được bổ sung và có một vài sự sửa đổi trong một số câu lệnh cũ. Sau đây là một số câu lệnh mới:
foreach: dùng cho việc thực hiện vòng lặp cho một tập hợp như mảng… Ví dụ:
foreach (string s in array)
Console.WriteLine(s);
lock: dùng để bao một đoạn code thành một section.
checked/unchecked: dùng để kiểm tra tràn trong các toán tử có đối số là số. Ví dụ như:
int x = Int32.MaxValue; x++;
{
x++;
}
unchecked
{
x++; }
}
---Switch
Trong C#, câu lệnh switch được thay đổi như sau:
1.Sau khi thực thi một câu lệnh case, chương trình sẽ không nhảy đến câu lệnh case kế tiếp. Ví dụ:
int var = 100;
switch (var)
{
case 100:
Console.WriteLine(“<Value is 100>”); // không dùng break
case 200:
Console.WriteLine(“<Value is 200>”); break;
}
Trong C++, kết quả sẽ là: <Value is 100><Value is 200>
Trong C#, bạn sẽ nhận được thông báo lỗi sau:
error CS0163: Control cannot fall through from one case label (‘case 100:’) to another
Tuy nhiên, bạn có thể làm như sau:
switch (var)
{
case 100:
case 200:
Console.WriteLine(“100 or 200<VALUE is 200>”);
break;
}
2.Bạn cũng có thể dùng hằng trong giá trị của case. Ví dụ như:
const string WeekEnd = “Sunday”;
const string WeekDay1 = “Monday”;
....
string WeekDay =
Console.ReadLine();
switch (WeekDay )
{
case WeekEnd:
Console.WriteLine(“It’s weekend!!”);
break;
case WeekDay1:
Console.WriteLine(“It’s Monday”);
break;
}
----Delegate
Delegate cho phép chúng ta lưu sự tham khảo hàm vào một biến. Trong C++, việc này giống như dùng và lưu con trỏ hàm và chúng ta hay dùng typedef. Ví dụ:
delegate int Operation(int val1, int val2);
public int Add(int val1, int val2)
{
return val1 + val2;
}
public int Subtract (int val1, int val2)
{
return val1- val2;
}
public void Perform()
{
Operation Oper;
Console.WriteLine(“Enter + or - “);
string optor = Console.ReadLine();
Console.WriteLine(“Enter 2 operands”);
string opnd1 = Console.ReadLine();
string opnd2 = Console.ReadLine();
int val1 = Convert.ToInt32 (opnd1);
int val2 = Convert.ToInt32 (opnd2);
if (optor == “+”)
Oper = new Operation(Add);
else
Oper = new Operation(Subtract);
Console.WriteLine(“ Result ={0}”, Oper(val1, val2));
}
Tính thừa kế và tính đa hình
Trong C# chỉ cho phép sự thừa kế đơn. Nếu bạn muốn thực hiện đa thừa kế, bạn có thể dùng interface. Ví dụ:
class Parent{
}
class Child : Parent
Hàm ảo
Từ khái niệm hàm ảo đến hiện thực khái niệm đa hình trong C# là như nhau, ngoại trừ việc bạn dùng từ khóa override đối với việc hiện thực hàm ảo trong lớp con. Lớp cha vẫn sử dụng từ khóa virtual. Lớp nào override phương thức ảo cũng sử dụng từ khóa override.
class Shape
{
public virtual void Draw()
{
Console.WriteLine(“Shape.Draw”);
}
}
class Rectangle : Shape
{
public override void Draw()
{
Console.WriteLine(“Rectangle.Draw”);
}
}
class Square : Rectangle
{
public override void Draw()
{
Console.WriteLine(“Square.Draw”);
}
}
class MainClass
{
static void Main(string[] args)
{
Shape[] shp = new Shape[3];
Rectangle rect =
new Rectangle();
shp[0] = new Shape();
shp[1] = rect;
shp[2] = new Square();
shp[0].Draw();
shp[1].Draw();
shp[2].Draw();
}
}
Xuất ra kết quả như sau:
Shape.Draw
Rectangle.Draw
Square.Draw
Ẩn lớp cha bằng cách dùng “new” Trong một lớp con, bạn có thể định nghĩa một hàm mới, ẩn với lớp cha, bằng cách dùng từ khóa new. Trong ví dụ dưới đây, là bản sửa đổi của ví dụ trên, tôi thay thế từ khóa override bằng từ khóa new trong lớp Rectangle.
class Shape
{
public virtual void Draw()
{
Console.WriteLine(“Shape.Draw”);
}
}
class Rectangle : Shape
{
public new void Draw()
{
Console.WriteLine(“Rectangle.Draw”);
}
}
class Square : Rectangle
{
public new void Draw()
{
Console.WriteLine(“Square.Draw”);
}
}
class MainClass
{
static void Main(string[] args)
{
Console.WriteLine(“Using Polymorphism:”);
Shape[] shp = new Shape[3];
Rectangle rect = new Rectangle();
shp[0] = new Shape();
shp[1] = rect;
shp[2] = new Square();
shp[0].Draw();
shp[1].Draw();
shp[2].Draw();
Console.WriteLine(“Using without Polymorphism:”);
rect.Draw();
Square sqr = new Square();
sqr.Draw();
}
}
Kết quả xuất ra như sau:
Using Polymorphism
Shape.Draw
Shape.Draw
Shape.Draw
Using without Polymorphism:
Rectangle.Draw
Square.Draw
Trong ví dụ trên, phương thức Draw của lớp Rectangle không phải là dạng đa hình của phương thức Draw trong lớp Shape. Thay vì vậy, nó được xem như là một phương thức khác. Do đó, để tránh sự trùng tên giữa lớp cha và lớp con, ta nên dùng từ khóa new.
Lưu ý: bạn không thể dùng hai phương thức cùng tên trong cùng một lớp nếu một phương thức dùng từ khóa new, phương thức kia dùng override hay virtual.
Do đó trong lớp Square, tôi không thể override phương thức Draw của lớp Shape. Gọi những member của lớp cha Nếu lớp con có dữ liệu member cùng tên với dữ liệu đó trong lớp cha, để tránh bị trùng tên, dữ liệu và hàm member của lớp cha được truy xuất thông qua từ khóa base. Trong ví dụ sau, hãy xem cách constructor của lớp cha được gọi và dữ liệu member được dùng:
public Child(int val) :base(val)
{
myVar = 5;
base.myVar;
}
Hay
public Child(int val)
{
base(val);
myVar = 5 ;
base.myVar;
}
---------------------------------------------------------------------------------------------------------------------------------------*** Vào ra dữ liệu trong C# (trong môi trường Console)
- C# hỗ trợ vào ra dữ liệu trong môi trường Console thông qua đối tượng Console. Đối tượng này nằm trong thư viện (namespace) có tên: System.
- Để khai báo thư viện sử dụng dòng lệnh:
using System;
- Để xuất dữ liệu (ra – output) chúng ta sử dụng 2 phương thức:
Write: phương thức này cho phép in dữ liệu ra màn hình Console theo định dạng. Dữ liệu có thể là các hằng số, các biến, các biểu thức.
Có tất cả 18 quá tải phương thức (overloadding method) để cho phép chúng ta có thể thực hiện in ra giá trị của các kiểu hằng số, biến khác nhau.
Trong đó có hàm tổng và thường được sử dụng nhất là:
->Cú pháp:
Console.Write(“chuỗi định dạng”,”danh sách các đối số”);
Trong đó:
“Chuỗi định dạng”: là chuỗi kí tự chỉ ra dạng hiển thị (trình bày của dữ liệu).
Chuỗi định dạng có thể là:
Các kí tự: kí tự số (0,2,3,4….9) hoặc các kí tự chữ ‘a’, ‘z’,’A’,’X’….’%’.
Các kí tự thoát (escape sequence): các kí tự thoát bắt đầu với dấu % hoặc dấu \. VD: kí tự điều khiển xuống dòng là
hoặc kí tự điều khiển nhẩy 1 Tab là \t.
Kí tự giữ chỗ (placeholder): các kí tự giữ chỗ này có dạng {n}. Trong đó n là số nguyên chỉ ra số thứ tự của đối số.
“danh sách các đối số”: là danh sách các biến hoặc các hằng số hoặc các biểu thức cách nhau bởi dấu phẩy (,). VD: -7, ‘a’, (a+b)*c, x…
VD: sử dụng lệnh Write để in ra giá trị tương ứng của các biến a, b, c và giá trị của biểu thức (a+b)*c.
int a, b, c;
a = 3;
b = -5;
c = 9;
Console.Write("a = {0}, b = {1}, c = {2}, fx = {3}",a,b,c,(a+b)*c);
++Chú ý:
Số lượng các placeholder trong chuỗi định dạng bằng với số lượng các đối số trong danh sách các đối số.
Giá trị số của các placeholder bắt đầu được đánh số thứ tự từ 0.
Thứ tự của các đối số sẽ tương ứng với thứ tự của các placeholder.
* WriteLine: hàm thực hiện in dữ liệu và chuyển con trỏ đến dòng tiếp theo trên màn hình Console.
- Hàm nhập dữ liệu (input): để nhập dữ liệu cho ứng dụng Console chúng ta có thể sử dụng các hàm sau:
Read: hàm read cho phép đọc 1 số nguyên từ vùng đệm bàn phím trong ứng dụng Console. Hàm này trả về 1 số nguyên.
ReadKey: hàm này cho phép đọc 1 phím từ bàn phím.
ReadLine: hàm này cho phép nhập 1 chuỗi kí tự.
Một số hàm liên quan đến quá trình nhập liệu khác:
Parse: hàm này thực hiện phân tích và chuyển đổi 1 kiểu dữ liệu thành một kiểu dữ liệu khác.
VD1: để chuyển 1 chuỗi kí tự thành 1 số nguyên thì dùng dòng lệnh.
int a;
a = int.Parse(Console.ReadLine());
VD2: để chuyển 1 chuỗi kí tự thành 1 số thực decimal thì dùng dòng lệnh.
decimal n;
n = decimal.Parse(Console.ReadLine());
Đối tượng Convert: là đối tượng cho phép biến đổi 1 kiểu dữ liệu bất kì thành 1 kiểu dữ liệu khác. Đối tượng này chứa các phương thức tĩnh tương ứng cho việc chuyển đổi các kiểu dữ liệu dữ liệu sang một kiểu dữ liệu nào đó. VD: để chuyển đổi sang số nguyên chúng ta có thể dùng các hàm ToInt16, ToInt32, ToInt64, chuyển sang số thực dùng các hàm ToFloat, ToDouble, ToDecimal…
VD:
a = Convert.ToInt32(Console.ReadLine());
2. Lệnh và các biểu thức
- Định nghĩa: lệnh là một nhóm logic các biến, các toán tử và các từ khóa để thực hiện 1 công việc cụ thể nào đó.
VD: lệnh để khai báo 1 hằng số thực PI có giá trị bằng 3.14.
const float PI = 3.14f;
- Các lệnh trong C# đều kết thúc bởi dấu chấm phẩy (.
- Định nghĩa: khối lệnh (block) là một nhóm các câu lệnh thực hiện 1 nhiệm vụ cụ thể nào đó. Các khối lệnh nằm trong cặp dấu { và }
VD: khối lệnh tính diện tích hình tròn.
{
float banKinh;
float dienTich;
Console.Write("Nhap ban kinh: ");
banKinh = float.Parse(Console.ReadLine());
dienTich = banKinh * banKinh * Math.PI;
Console.WriteLine("Dien tich: {0}", dienTich);
Console.ReadLine();
}
3. Các kiểu lệnh
Có 7 kiểu lệnh trong C#:
- Các lệnh lựa chọn (Selection Statements): là những lệnh tạo ra quyết định một đoạn mã lệnh nào đó có được thực hiện hay ko dựa vào một điều kiện. Một số lệnh thuộc nhóm này: if, switch.
- Các lệnh lặp (Iteration Statements): là cấu trúc lệnh giúp chúng ta thực hiện lặp đi lặp lại một đoạn mã lệnh cho đến khi thỏa mãn một điều kiện nào đó. Các lệnh thuộc nhóm này: for, foreach, do, while.
- Các lệnh nhảy (Jump Statements): là các lệnh giúp chúng ta chuyển luồng thực hiện của chương trình (flow of program) từ một đoạn mã lệnh này sang một đoạn mã lệnh khác. Các lệnh thuộc nhóm này: break, continue, return, goto, default, yield.
- Các lệnh xử lý ngoại lệ (Exception Handling Statements): là các lệnh được sử dụng để kiểm soát những tình huống ko mong muốn xảy ra trong ứng dụng của chúng ta và làm cho ứng dụng hoạt động sai hoặc bị phá vỡ. Các lệnh thuộc nhóm này: try, catch, finally, throw.
- Các lệnh được kiểm tra và ko được kiểm tra (Checked and UnChecked Statements): những lệnh ko được kiểm tra là những lệnh sẽ được bỏ qua bởi trình quản lý code (CLR) còn những lệnh được kiểm tra là những lệnh sẽ được kiểm soát bởi CLR. Và để chỉ ra những lệnh nào là được kiểm tra và ko được kiểm tra thì chúng ta sử dụng các từ khóa tương ứng là: checked và unchecked. Mặc định các lệnh đều thuộc nhóm checked.
- Các lệnh fixed: các lệnh fixed được sử dụng để chỉ ra cho GC (trình thu gom rác – Garbage Collector) là sẽ bỏ qua việc thu hồi bộ nhớ được sử dụng bởi các đối tượng trong đoạn lệnh fixed này. Các từ được sử dụng là: fixed và unsafe.
- Các lệnh khóa (Lock Statements): là các lệnh giúp cho việc khóa các đoạn code quan trọng để đảm bảo rằng các tiến trình (process) hoặc các tuyến đoạn (thread) khác có thể can thiệp vào bộ nhớ mà đang được sử dụng bởi đoạn lệnh nào đó. Các lệnh này được sử dụng để đảm bảo tính bảo mật và chỉ hoạt động trên các kiểu dữ liệu tham chiếu. Từ khóa được sử dụng là lock.
8. Các biểu thức
- Biểu thức (expression) là một sự kết hợp của các toán tử (operators) và các toán hạng (operands).
- Toán tử là một kí hiệu để chỉ ra thao tác trên dữ liệu. VD: + để chỉ ra thao tác tính tổng 2 số…
- Toán hạng có thể là các hằng số, các biến hoặc các hàm. VD: -7, x, Sin(PI/180)…
- Một số VD về biểu thức:
x+y
(x-y)/(x+y)
Sin(x*x)/2+5*y
- Để gán giá trị của một biểu thức vào một biến chúng ta sử dụng toán tử gán (assignment operator). Cú pháp:
[tên biến] = [biểu thức];
9. Các kiểu toán tử
Có 6 kiểu toán tử:
- Toán tử toán học (Arithmetic Operators): là các toán tử được sử dụng để thực hiện các thao tác tính toán toán học ví dụ như: tính tổng, hiểu, tích, thương, lấy phần dư….
Một số các toán tử toán học:
+ : tính tổng
- : tính hiệu
* : tính tích
/ : tính thương
% : lấy phần dư của phép chia a cho b
- : toán tử âm.
- Toán tử quan hệ (Relational Operators): là những toán tử được sử dụng để kiểm tra mối quan hệ giữa các toán hạng.
> : kiểm tra lớn hơn
< : kiểm tra nhỏ hơn
= = : kiểm tra bằng nhau
!= : kiểm tra khác nhau
>= : kiểm tra lớn hơn hoặc bằng
<= : kiểm tra nhỏ hơn hoặc bằng
- Toán tử logic (Logical Operators): là những toán tử được sử dụng để liên kết các toán hạng, các biểu thức với nhau.
&& : toán tử VÀ.
|| : toán tử HOẶC.
! : toán tử PHỦ ĐỊNH.
- Các toán tử trên bit (Bitwise Operators): là các toán tử thực hiện các thao tác logic trên bit.
& : và logic trên bit.
| : hoặc logic trên bit.
^ : toán tử lấy phần bù.
- Các toán tử tăng và giảm (Increment and Decrement Operators): các toán tử này được sử dụng để tăng hoặc giảm giá trị của biến.
-- : giảm giá trị của biến xuống 1 đơn vị.
++ : tăng giá trị của biến lên 1 đơn vị.
- Toán tử gán (Assignment Operator): được sử dụng để gán giá trị của một hằng số hoặc một biến hoặc 1 biểu thức cho một biến.
Toán tử gán sử dụng dấu =.
10. Chuyển đổi dữ liệu trong C#
- Trong quá trình xây dựng chương trình thì cần có sự chuyển đổi linh hoạt giữa các loại dữ liệu được sử dụng trong chương trình.
- Sự chuyển đổi này có 2 loại:
o Chuyển đổi ngầm định (Implicit conversion): chuyển đổi ngầm định được sử dụng trong trường hợp chúng ta chuyển dữ liệu từ một kiểu dữ liệu có phạm vi lưu trữ thấp sang một kiểu dữ liệu có phạm vi lưu trữ lớn hơn.
VD: chuyển dữ liệu từ kiểu số nguyên sang kiểu số thực.
int x = -7;
float y = x; // implicit conversion.
o Chuyển đổi ép buộc - rõ ràng (Explicit conversion): kiểu chuyển đổi được sử dụng trong trường hợp chúng ta muốn chuyển dữ liệu từ một kiểu dữ liệu có phạm vi lưu trữ lớn hơn về một kiểu dữ liệu có phạm vi lưu trữ nhỏ hơn.
VD: chuyển dữ liệu từ kiểu số thực về số nguyên.
float x1 = -3.76f;
int x2 = (int)x1; // explicit conversion.
- Một hình thức chuyển đổi kiểu dữ liệu khác đó là chuyển đổi dữ liệu từ kiểu dữ liệu tham trị sang kiểu dữ liệu tham chiếu và ngược lại.
o Nếu chúng ta chuyển từ kiểu dữ liệu tham trị sang tham chiếu thì gọi là Boxing. Boxing ko sử dụng toán tử ép kiểu.
VD:
int n1 = -9; // value type.
object o1 = n1; // value type -> reference type: Boxing.
o Nếu chúng ta chuyển kiểu dữ liệu từ kiểu tham chiếu sang kiểu tham trị thì gọi là UnBoxing. Để thực hiện UnBoxing thì phải ép kiểu.
VD:
int n1 = -9; // value type.
object o1 = n1; // value type -> reference type: Boxing.
int n2 = (int)o1; // reference type -> value type: UnBoxing.
-------------------
** Các cấu trúc điều khiển
Cấu trúc if:
Cấu trúc if trong C# được mô tả như sau:
if (biểu thức điều kiện)
{
// câu lệnh thực thi nếu biểu thức điều kiện đúng
}
[else
{
// câu lệnh thực thi nếu biểu thức điều kiện sai
}]
Ví dụ:if (20 % 4 > 0)
{
Console.WriteLine("Số 20 không chia hết cho 4");
}
else
{
Console.WriteLine("Số 20 chia hết cho số 4");
}
Cấu trúc switch … case
Cấu trúc swtich….case có cấu trúc như sau:
// switch ... case
switch (Biến điều kiện)
{
case giá trị 1:
Câu lệnh thực thi
break;
case giá trị 2:
Câu lệnh thực thi
break;
case giá trị 3:
Câu lệnh thực thi
break;
default:
Câu lệnh thực thi
break;
}
Ví dụ:int x = 20 % 4;
switch (x)
{
case 1:
Console.WriteLine("20 chia cho 4 được số dư là 1");
break;
case 0:
Console.WriteLine("20 chia hết cho 4");
break;
default:
Console.WriteLine("Không thuộc tất cả các trường hợp trên");
break;
}
2. Cấu trúc vòng lặp trong lập trình C#
C# cung cấp các cấu trúc vòng lặp chương trình
§ While
§ Do… while
§ For
§ Foreach
Sau đây, tôi xin giới thiệu công thức và ví dụ sử dụng các vòn lặp trên
Vòng lặp While
Cấu trúc vòng lặp while
while (biểu thức điều kiện)
{
// câu lệnh
}
Thực thi câu lệnh hoặc một loạt những câu lệnh đến khi điều kiện không được thỏa mãn.
Ví dụ:
using System;
class WhileTest
{
public static void Main()
{
int n = 1;
while (n < 10)
{
Console.WriteLine("Current value of n is {0}", n);
n++;
}
}
}
Vòng lặp do
Cấu trúc vòng lặp while
do
{
// câu lệnh
}
While (biểu thức điều kiện)
Thực thi câu lệnh ít nhất một lần đến khi điều kiện không được thỏa mãn.
Ví dụ:using System;
public class TestDoWhile
{
public static void Main ()
{
int x;
int y = 0;
do
{
x = y++;
Console.WriteLine(x);
}
while(y < 10)
}
}
Vòng lặp for
Cấu trúc vòng lặp for
for ([ phần khởi tạo] ; [biểu thức điều kiện]; [bước lặp])
{
// thực thi câu lệnh
}
Ví dụ:using System;
public class ForLoopTest
{
public static void Main()
{
for (int i = 1; i <= 5; i++)
Console.WriteLine(i);
}
}
Vòng lặp foreach
Câu lệnh lặp foreach khá mới với những người đã học ngôn ngữ C, từ khóa này được sử dụng trong ngôn ngữ Visual Basic. Câu lệnh foreach cho phép chúng ta lặp qua tất cả các mục trong một mảng hay trong một tập hợp. Cú pháp sử dụng lệnh lặp foreach như sau:
foreach (var item in collection )
{
// thực hiện thông qua tương ứng với
// từng mục trong mảng hay tập hợp
}
Dữ liệu kiểu tập hợp chưa được đề cập tới trong các bài học trước nên bạn chỉ cần quan tâm đến vòng lặp foreach sử dụng với mảng. Bạn hãy xem ví dụ sau để hiểu cách sử dụng của vòng lặp foreach truy cập đến từng phần từ của mảng.
using System;
public class UsingForeach
{
public static int Main()
{
int[] intArray = {1,2,3,4,5,6,7,8,9,10};
foreach( int item in intArray)
{
Console.Write("{0} ", item);
}
Console.ReadLine();
return 0;
}
}
Kết quả:
0 1 2 3 4 5 6 7 8 9 10
3. Các lệnh break, goto và continue
Câu lệnh nhảy goto:
Lệnh nhảy goto là một lệnh nhảy đơn giản, cho phép chương trình nhảy vô điều kiện tới một vị trí trong chương trình thông qua tên nhãn. Goto giúp chương trình của bạn được linh hoạt hơn nhưng trong nhiều trường hợp nó sẽ làm mất đi cấu trúc thuật toán và gây rối chương trình.
Cách sử dụng lệnh goto:
Tạo một nhãn
goto đến nhãn
Nhãn là một định danh theo sau bởi dấu hai chấm (:). Thường thường một lệnh goto gắn với
một điều kiện nào đó.
Ví dụ:
public class UsingGoto
{
public static void Main()
{
int i = 0;
lap: // nhãn
Console.WriteLine("i:{0}",i);
i++;
if ( i < 10)
goto lap; // nhãy về nhãn lap
Console.ReadLine();
}
}
Tương đương với vòng lặp for sau:
for (int i = 0; i < 10; i++)
Console.WriteLine("i:{0}", i);
Câu lệnh nhảy break và continue
Khi đang thực hiện các lệnh trong vòng lặp, có yêu cầu như sau: không thực hiện các
lệnh còn lại nữa mà thoát khỏi vòng lặp, hay không thực hiện các công việc còn lại của vòng
lặp hiện tại mà nhảy qua vòng lặp tiếp theo. Để đáp ứng yêu cầu trên C# cung cấp hai lệnh
nhảy là break và continue để thoát khỏi vòng lặp.
Break khi được sử dụng sẽ đưa chương trình thoát khỏi vòng lặp và tiếp tục thực hiện các
lệnh tiếp ngay sau vòng lặp.
Continue ngừng thực hiện các công việc còn lại của vòng lặp hiện thời và quay về đầu vòng
lặp để thực hiện bước lặp tiếp theo.
Ví dụ:
public class UsingBreak_Continue
{
public static void Main()
{
for (int i = 0; i < 10; i++)
{
if (i % 2 == 0) continue;
Console.WriteLine("i:{0}", i);
if (i==7) break;
}
Console.ReadLine();
}
}
Nếu không có lệnh break và continue vòng lặp sẽ lần lượt in ra các số từ 0 đến 9 nhưng khi gặp I chẵn (i%2==0) thì nó sẽ continue – tức là không thực hiện các lệnh tiếp theo mà quay trở lại đầu vòng lặp với giá trị của I được tăng lên 1. Lệnh break được thực hiện khi (i==7) nó sẽ thoát khỏi vòng lặp ngay lập tức và cũng kết thúc chương trình và kết quả là chương trình trên chỉ in ra các số lẻ từ 1 đến 7
---------------------------------------------------------------------------------------------------------------------------------------
ĐỐI TƯỢNG VÀ LỚP
Mục tiêu: Sau khi tìm hiểu xong chương này người học có thể nắm được các nội dung sau:
● Khai báo lớp
● Khai báo và sử dụng các đối tượng của lớp
● Từ khóa this
● Các thuộc tính truy cập
● Hàm thiết lập
● Hàm thiết lập sao chép
● Hàm hủy bỏ
● Sử dụng các thành viên tĩnh
● Nạp chồng phương thức
● Đóng gói dữ liệu thông qua các thuộc tính
A. TÓM TẮT LÝ THUYẾT
1. Khai báo lớp
Một lớp bao gồm có các thuộc tính và phương thức. Để khai báo một lớp ta sử dụng từ khóa class với cấu trúc sau đây:
[Thuộc tính truy cập] class <tên lớp>
{
Khai báo các thuộc tính của lớp
Khai báo các phương thức của lớp
}
Các thuộc tính truy cập gồm có các từ khóa sau đây (sẽ trình bày chi tiết ở phần sau): public, private, internal, protected, internal protected.
Trong C#, cho phép chúng ta khai báo các class lồng nhau. Thông thường khai báo lớp lồng nhau khi ứng dụng có quy mô lớn. Class lồng cho phép sử dụng trong nội bộ class chứa nó khi nó có tầm vực public.
Cấu trúc khai báo một class lồng như sau:
class class1
{
// khai báo thuộc tính
// khai báo các phương thức
public class class2
{
// khai báo các thành phần dữ liệu
// khai báo các phương thức
}
}
2. Sử dụng các đối tượng của lớp:
Để sử dụng lớp ta phải khai báo đối tượng của lớp đó. Khi một đối tượng của lớp được tạo ra thì nó có đầy đủ các thuộc tính, phương thức của lớp và sử dụng thuộc tính và phương thức của lớp. Các thành phần của một lớp chỉ đuợc sử dụng khi có thể hiện của lớp, trừ trường hợp trong lớp có một hàm khởi dựng là static. Để khai báo một đối tượng của lớp ta dùng từ khóa new và khai báo nó theo cấu trúc sau:
<tên lớp> <tên đối tượng> = new <tên lớp> ([các giá trị khởi tạo nếu có])
Để truy nhập đến một phương thức ta thông qua tên biến đối tượng và toán tử chấm “.”:
<tên đối tượng>. <tên phương thức> ([danh sách các đối số nếu có])
Đối với các lớp lồng nhau, để truy cập đến những thuộc tính và phương thức của class lồng thì khi khai báo cần chỉ ra lớp chứa đựng nó. Muốn sử dụng biến của lớp chứa thì các biến của lớp dùng để chứa phải khai báo là static và phải khai báo đối tượng chứa nó.
Ví dụ1: Bạn đã khai báo một lớp diem với đầy đủ các thuộc tính và các phương thức (giả sử là có phương thức hien()), bây giờ bạn muốn tạo một đối tuợng tên là A của lớp này và sử dụng phương thức hiện điểm A thì phải khai báo A la một biến đối tượng như sau:
diem A = new diem ();
A.hien();
Ví dụ 2: Định nghĩa lớp pheptoan và trong lớp này có chứa lớp tinhhieu, muốn sử dụng đối tượng của lớp tinhhieu thì bắt buộc bạn phải khai báo chỉ rõ lớp chứa ở đây là lớp pheptoan như sau:
pheptoan.tinhhieu con = new pheptoan.tinhhieu();
sau đó việc truy xuất đến các phương thức của lớp thì tiến hành bình thường nhưng lớp ở trong thì không sử dụng được phương thức của lớp chứa nó và chỉ sử dụng được thành phần dữ liệu tĩnh của lớp chứa mà thôi.
3. Từ khóa this
Từ khóa this dùng để tham chiếu đến chính bản thân của đối tượng đó.this là một con trỏ ẩn nằm ngay bên trong của mỗi một phương thức của lớp và bản thân chúng có thể tham chiếu đến các hàm và các biến khác của một đối tượng. Từ khóa this trong C# cũng tương tự như this trong C++.
Có ba cách để sử dụng từ khóa this.
- Sử dụng this để phân biệt rõ giữa các thành viên thể hiện và các tham số của phương thức khi ta sử dụng biến thể hiện và tên của tham số trong phương thức trùng nhau. Tuy nhiên nếu muốn có đựơc sự rõ ràng, minh bạch thì có thể dùng tên biến thành viên và tên tham số là khác nhau từ đầu.
Ví dụ: Trong lớp pheptoan có biến thành viên là int y, int y và phương thức
public int setXY(int x, int y)
{
this.x=x;
this.y=y;
}
this.x, this.y là để tham chiếu đến 2 thành phần dữ liệu của lớp x, y. Còn x, y ở bên phải phép gán chính là hai đối số truyền vào của phương thức setXY
- Sử dụng this để trao đối tượng hiên hành như là một thông số cho một hàm hành sự khác. Khi đó một đối tượng đương nhiên sẽ trở thành một tham số của phương thức.
Ví dụ: với hai lớp class1 có chứa phương thức thietlapdoituong(), lớp class2 có chứa phương thức saochepdoituong() và muốn truyền tham số cho nó là đối tượng của lớp class1 thì sử dụng từ khóa thí như sau:
public void saochepdoituong (class1 a)
{
a.thietlapdoituong(this);
}
- Sử dụng this để thao tác với các indexer thường được sử dụng trong bản dãy, indexer và các tập hợp.
4 . Bộ khởi dựng( constructor/ Phương thức khởi tạo/ thiết lập)
Cú pháp:
public className([ds tham số])
{
// Khởi tạo cho các thành phần dữ liệu của lớp
}
trong đó className: Tên lớp
Chú ý: Phương thức khởi tạo là phương thức có tên trùng với tên của lớp và không có kiểu trả về
5. Sử dụng các từ khóa mức độ truy cập
+ public : Không có giới hạn, có thể truy xuất mọi nơi trong bản thân lớp khai báo và bên ngoài hay trong nội bộ khối assembly.
+ private: riêng tư chỉ có phạm vi hoạt động trong lớp mà nó khai báo. Các phương thức bên ngoài lớp không thể truy xuất đến nó.
+ protected: Các thành viên trong lớp được khai báo bằng protected thì chỉ có các phương thức bên trong lớp và các lớp dẫn xuất từ lớp đó mới có thể truy cập đến nó.
+ internal: Các phương thức, các biến thành viên được khai báo bằng từ khóa Internal có thể được truy cập bởi tất cả những phương thức của bất cứ lớp nào trong cùng một khối hợp ngữ assembly với lớp đó.
+ protected internal: Các biến thành viên được khai báo bằng từ khóa này trong một lớp A bất kì có thể được truy xuất bởi các phương thức thuộc lớp A và các phương thức của lớp dẫn xuất từ lớp A và bất cứ lớp nào trong cùng một khối hợp ngữ với lớp A.
- Khối hợp ngữ Assembly được hiểu là một khối chia xẻ và dùng lại trong CLR. Khối hợp ngữ là tập hợp các tập tin vật lý được lưu trữ trong một thư mục bao gồm các tập tin tài nguyên.
Các thuộc tính truy cập được áp dụng cho thuộc tính, phương thức của lớp và bản thân lớp. Khi định nghĩa thuộc tính truy cập của lớp là internal, protected chỉ được định nghĩa trong lớp lồng nhau mà thôi.
Bạn đang đọc truyện trên: TruyenTop.Vip