Một chương trình Java bao gồm nhiều lớp (classes) để thể hiện cho nhiều đối tượng trong thế giới thực. Vì Java là ngôn ngữ hướng đối tượng, do đó để trở thành một lập trình viên giỏi đòi hỏi bạn phải biết quyết định được những đối tượng nào cần phải có trong chương trình và các lớp Java sẽ đại diện cho chúng. Khi đã hoàn thành việc xác định đối tượng thì lập trình viên mới bắt tay vào viết mã code.
Làm quen với lớp và đối tượng trong Java

Java Class là gì

  • Các lớp trong Java có thể có nhiều phương thức và nhiều thuộc tính.
  • Các phương thức định nghĩa các hành động mà một lớp có thể thực hiện.
  • Các thuộc tính đặc tả cho lớp.
Để bắt đầu làm quen với bài học, chúng ta sẽ cùng thảo luận về một lớp có tên là Dog đại diện cho một đối tượng rất gần gũi trong đời sống thực của chúng ta. Lớp Dog này sẽ có một vài phương thức như: say(), eat() và sleep(). Lớp này cũng sẽ có một vài thuộc tính như: name, breed, color, và age.

Trong ngôn ngữ Java, chúng ta có thể định nghĩa lớp Dog như sau:
Dog.java
public class Dog {
  String name;
  String breed;
  String color:
  int age;
  
  public void eat() {
  }

  public void sleep() {
  }

  public String say(String words) {
  }
}

Tạo Instance cho đối tượng

Như ở phần đầu bài viết tôi đã có nói đến, class (lớp) đại diện cho một đối tượng cụ thể và chúng ta có thể tạo ra các Instance cho đối tượng bằng từ khóa new. Điều đó có nghĩa rằng chúng ta có thể tạo ra hàng nhìn các bản sao của đối tượng trong bộ nhớ máy tính dựa trên định nghĩa của lớp.

Như chúng ta đã có đối tượng là Dog, được định nghĩa bởi lớp Dog.java, bây giờ chúng ta có thể tạo ra các thể hiện cho lớp Dog thông qua từ khóa new.

Trước khi khởi tạo các instance cho đối tượng Dog. Chúng ta sẽ bổ sung một số thay đổi cho các phương thức để in ra message như sau nhé.
  • Phương thức eat() in ra message là "I'm so hungry... Let me have a snake like nachos!". Phương thức này không nhận bất kỳ tham số đầu vào nào và không trả về bất kỳ giá trị nào
  • Tương tự, phương thức sleep() sẽ chỉ in ra một thông điệp là "Good night, see you tomorrow".
  • Phương thức say(), sẽ xây dựng một thông điệp dựa trên một từ hoặc cụm từ mà chúng ta truyền vào cho tham số (parameter). Các tham số khi được truyền vào từ instance gọi là đối số (argument). Sau khi xây dựng nó sẽ trả về thông điệp cho instance.
Sau khi bổ sung, các phương thức của lớp Dog sẽ trông như sau:
public class Dog {
 String name;
  String breed;
  String color:
  int age;
  
  public void eat() {
    System.out.println("I'm so hungry... Let me have a snake like nachos!");
  }

  public void sleep() {
    System.out.println("Good night, see you tomorrow");
  }

  public String say(String words) {
      String message = "OK!! OK!! " + words;
      return message;
  }
}
Bây giờ chúng ta cùng nói về phương thức public void eat(). Từ định nghĩa, nó cho chúng ta biết rằng phương thức này có thể gọi từ một lớp khác thông qua instance của nó (từ khóa public) và không trả về bất kỳ dữ liệu nào (từ khóa void). Hai dấu ngoặc đơn () trống có nghĩa rằng chúng ta không nhận bất kỳ đối số nào. Nó không cần bất kỳ dữ liệu nào từ bên ngoài truyền vào và luôn in ra 1 cùng 1 đoạn text.

Đối với phương thức public String say(String words).
Phương thức này cũng sẽ được gọi từ bất kỳ một lớp Java khác nào đó thông qua biến instance của đối tượng Dog. Nó sẽ trả về dữ liệu với kiểu String, điều này bạn có thế thấy bởi từ khóa String được khai báo trước tên phương thức. Bên cạnh đó, phương thức này yêu cầu dữ liệu được truyền vào từ bên ngoài, do đó nó bao gồm parameter là String words giữa 2 dấu ngoặc đơn.

Làm thế nào để bạn quyết định được khi nào thì phương thức nên hay không nên trả về dữ liệu khi được gọi? Rất đơn giản, nếu phương thức của bạn thực hiện 1 vài thao tác xử lý dữ liệu và sau đó trả về kết quả từ những xử lý này cho lớp đang gọi thì nó cần trả về 1 giá trị.

OK, tiếp theo chúng ta sẽ xây dựng một lớp mới có tên là DogMaster. Lớp này sẽ bao gồm phương thức main() và bạn có thể khởi tạo instance cho đối tượng Dog sau đó gọi các phương thức thông qua instance để xem nó như thế nào nhé.
DogMaster.java
public class DogMaster {

  public static void main(String[] args) {
   String dogReaction;
   Dog myDog = new Dog();
  
   myDog.eat();
   dogReaction = myDog.say("Tweet!! Tweet!!");
   System.out.println(dogReaction);

   myDog.sleep();
  }
}
Bây giờ bạn có thể biên dịch và chạy chương trình, nó sẽ in ra màn hình kết quả giống như sau:
I'm so hungry...let me have a snake like nachos!
OK!! OK!! Tweet!! Tweet!!
Good night, see you tomorrow

Lớp DogMaster là lớp đang gọi các phương thức của đối tượng Dog thông qua instance là myDog. Như vậy, bạn đã biết cách tạo ra một instance cho đối tượng Dog thông qua từ khóa new rồi đúng không nào.
Dog myDog = new Dog();
Dòng này khai báo 1 biến kiểu Dog (Bạn có thể xử lý bất kỳ các lớp đã tạo bằng cách khai báo nó như một kiểu dữ liệu mới). Bây giờ chúng ta có biến myDog, biến này được biết đến như là một instance của đối tượng Dog. Nó được tạo ra trong bộ nhớ và bạn có thể sử dụng biến này để gọi các phương thức của lớp Dog. Ví dụ như
myDog.eat();
Nếu phương thức được gọi sẽ trả về dữ liệu, bạn cần khai báo 1 biến có cùng kiểu dữ liệu với kiểu trả về của phương thức đó và gán cho biến này. Như trong ví dụ trên ta đã khai báo như sau:
String dogReaction;
dogReaction = myDog.say("Tweet!! Tweet!!");
Giá trị trả về của phương thức say() sẽ được lưu vào biến dogReaction và bây giờ bạn có thể thao tác trên biến này. Như trong ví dụ chúng ta sẽ in giá trị của nó ra màn hình bằng dòng lệnh
System.out.println(dogReaction);

Constructor là gì?

Trong ví dụ trên, chúng ta đã có thể tạo ra biến instance cho đối tượng Dog dựa trên định nghĩa của lớp Dog.java. Và bạn cũng đã sử dụng qua constructor của lớp này từ câu lệnh.
Dog myDog = new Dog();
Trong đó Dog() là constructor không có đối số. Đây là constructor mặc định được Java complier xây dựng nếu như bạn không viết bất kỳ một constructor nào cho lớp của bạn.

Mỗi khi đối tượng mới được tạo ra, thì constructor sẽ được gọi ít nhất 1 lần. Constructor là phương thức khởi tạo và nó phải có cùng tên với tên của class. Mỗi class có thể có 1 hoặc nhiều phương thức khởi tạo.

Ví dụ chúng ta có thể tạo ra các constructor cho lớp Dog như sau:

public class Dog {
  // Phần khai báo thuộc tính...
  public Dog() {
  }
  public Dog (String name) {
    // Constructor này có 1 tham số là name.
  }
  // Phần khai báo các phương thức ...
}

Cuối cùng, chúng ta có thể có một chương trình hoàn chỉnh như sau:

Dog.java
public class Dog {
  String name;
  String breed;
  String color:
  int age;
  public Dog () {
  }  

  public Dog (String name, String breed, String color, int age) {
   this.name = name;
   this.breed = breed;
   this.color = color;
   this.age = age;
  }
 
  public void eat() {
    System.out.println("I'm so hungry... Let me have a snake like nachos!");
  }

  public void sleep() {
    System.out.println("Good night, see you tomorrow");
  }

  public String say(String words) {
    String message = "OK!! OK!! " + words;
    return message;
  }

  public String toString() {
   return "Name = " + this.name + ", Breed = " + this.breed + ", Color = " + this.color
          + ", Age = " + this.age + " months";
  }
}

DogMaster.java
public class DogMaster {

  public static void main(String[] args) {
   String dogReaction;
   Dog myDog = new Dog("Rocky", "Alaskan Malamute", "White", 12);
   System.out.println(myDog);

   myDog.eat();
   dogReaction = myDog.say("Tweet!! Tweet!!");
   System.out.println(dogReaction);

   myDog.sleep();
  }
}
Thử biên dịch và chạy chương trình để xem kết quả.

Lời kết

Một bài học khá dài và tôi hi vọng rằng các bạn đọc giả có thể hiểu được ý định mà tôi muốn truyền tải. Qua đây chúng ta đã học được một số khái niệm về đối tượng, lớp, instance, phương thức và constructor. Hi vọng rằng bài viết sẽ hữu ích và giúp các bạn tiếp cận Java tốt hơn. Chúc các bạn học tốt nhé.