Phần biệt this và super trong Java

Giới thiệu từ khóa super và this. Đây là 2 từ khóa trong kế thừa. Phân biệt hai từ khóa cơ bản này bằng cách đi thẳng ví dụ minh chứng.

Nội dung chính

Show

  • Sự Khác Nhau Cơ Bản Giữa Từ Khóa Super Và This.
  • Sự sử dụng của từ khóa super trong Java
  • super được để tham chiếu biến instance của lớp cha gần nhất
  • super() được sử dụng để triệu hồi Constructor của lớp cha gần nhất
  • super được sử dụng để triệu hồi phương thức của lớp cha gần nhất
  • Video liên quan

Phần biệt this và super trong Java

Sự Khác Nhau Cơ Bản Giữa Từ Khóa Super Và This.

Để truy cập đến class cha từ class con để gọi hàm và biến ta sử dụng từ khoá super. Từ khóa this dùng để trỏ đến class hiện tại của chính nó. Để hiểu chi tiết hơn hãy cùng Trung Tâm JAVA thực hành chi tiết. Phần thực hành đã được quay lại video dưới đây:

Các kênh theo dõi bài học và thông tin khóa học

Kênh  youtube: Trung Tâm JAVA.

Website: http://trungtamjava.com

Fanpage fabook: https://www.facebook.com/trungtamjava/?fref=ts

Chúc các bạn học tập thật tốt

Trung Tâm JAVA truyền cảm hứng tới học viên và mang hướng đi với tới dân lập trình.

Từ khóa super trong Java là một biến tham chiếu mà được sử dụng để tham chiếu đến đối tượng lớp cha gần nhất. Bất cứ khi nào bạn tạo instance (sự thể hiện) của lớp con, một instance của lớp cha được tạo ngầm định, được tham chiếu bởi biến super.

Sự sử dụng của từ khóa super trong Java

  • super được sử dụng để tham chiếu biến instance của lớp cha gần nhất.
  • super() được sử dụng để triệu hồi Constructor của lớp cha gần nhất.
  • super được sử dụng để triệu hồi phương thức của lớp cha gần nhất.

Phần tiếp theo, chúng ta sẽ tìm hiểu chi tiết từng sự sử dụng của từ khóa super trong Java.

super được để tham chiếu biến instance của lớp cha gần nhất

Vấn đề xảy ra nếu không có từ khóa super:

class Vehicle{
int speed=50;
}
class Bike3 extends Vehicle{
int speed=100;
void display(){
System.out.println(speed); //se in speed cua Bike
}
public static void main(String args[]){
Bike3 b=new Bike3();
b.display();
}
}

Trong ví dụ trên, cả hai lớp Vehicle và Bike có cùng thuộc tính speed chung. Biến instance của lớp hiện tại được tham chiếu bởi instance theo mặc định, nhưng mình phải tham chiếu tới biến instance của lớp cha, và đó là tại sao chúng ta sử dụng từ khóa super để phân biệt giữa biến instance của lớp cha và biến instance của lớp hiện tại.

Xử lý vấn đề với từ khóa super trong Java:

//Chuong trinh vi du tu khoa super
class Vehicle{
int speed=50;
}
class Bike4 extends Vehicle{
int speed=100;
void display(){
System.out.println(super.speed); //bay gio se in speed cua Vehicle
}
public static void main(String args[]){
Bike4 b=new Bike4();
b.display();
}
}

super() được sử dụng để triệu hồi Constructor của lớp cha gần nhất

Bạn theo dõi ví dụ sau:

class Vehicle{
Vehicle(){System.out.println(“Vehicle duoc tao”);}
}
class Bike5 extends Vehicle{
Bike5(){
super();//se trieu hoi constructor cua lop cha
System.out.println(“Bike duoc tao”);
}
public static void main(String args[]){
Bike5 b=new Bike5();
}
}

Ghi chú: super() được tự động thêm vào trong mỗi Constructor của lớp bởi Compiler.

Qua các chương trước, chúng ta đã biết rằng constructor mặc định được cung cấp bởi Compiler nhưng nó cũng thêm super() cho lệnh đầu tiên. Nếu bạn đang tạo constructor cho riêng mình và bạn không có this() hoặc super() như là lệnh đầu tiên, thì Compiler sẽ cung cấp super() như là lệnh đầu tiên của Constructor đó.

Một ví dụ khác về từ khóa super, trong ví dụ này super() được cung cấp ngầm định bởi Compiler.

class Vehicle{
Vehicle(){System.out.println(“Vehicle duoc tao”);}
}
class Bike6 extends Vehicle{
int speed;
Bike6(int speed){
this.speed=speed;
System.out.println(speed);
}
public static void main(String args[]){
Bike6 b=new Bike6(10);
}
}

super được sử dụng để triệu hồi phương thức của lớp cha gần nhất

Từ khóa super cũng có thể được sử dụng để triệu hồi phương thức lớp cha gần nhất. Nó nên được sử dụng trong lớp con mà có chứa cùng phương thức như lớp cha, như trong ví dụ sau:

class Person{
void message(){System.out.println(“Chao mung”);}
}
class Student16 extends Person{
void message(){System.out.println(“Chao mung ban den voi java”);}
void display(){
message();//se trieu hoi phuong thuc message() cua lop hien tai
super.message();//se trieu hoi phuong thuc message() cua lop cha
}
public static void main(String args[]){
Student16 s=new Student16();
s.display();
}
}

Trong ví dụ trên, cả hai lớp Student và Person cùng có phương thức message(), nếu chúng ta gọi phương thức message() từ lớp Student, nó sẽ gọi phương thức message() của lớp Student chứ không phải của lớp Person bởi vì quyền ưu tiên cục bộ.

Trong tình huống mà không có phương thức nào của lớp con giống lớp cha, thì không cần sử dụng từ khóa super. Trong ví dụ dưới đây, phương thức message() được triệu hồi từ lớp Student, nhưng lớp Student không có phương thức message() này, vì thế bạn có thể trực tiếp gọi phương thức message().

Ví dụ chương trình không cần từ khóa super:

class Person{
void message(){System.out.println(“Chao mung”);}
}
class Student17 extends Person{
void display(){
message();//se trieu hoi phuong thuc message() cua lop cha
}
public static void main(String args[]){
Student17 s=new Student17();
s.display();
}
}

Khi viết mã, bạn thường không muốn lặp lại chính mình. Nếu bạn có một lớp có thể được xây dựng với nhiều tham số khác nhau, giải pháp phổ biến để tránh lặp lại chính mình là chỉ cần gọi một hàm tạo khác với các giá trị mặc định trong các đối số bị thiếu. Chỉ có một hạn chế khó chịu đối với điều này – nó phải là dòng đầu tiên của hàm tạo đã khai báo. Thí dụ:

MyClass()
{
this(default1, default2);
}
MyClass(arg1, arg2)
{
validate arguments, etc…
note that your validation logic is only written once now
}

Đối với hàm super()tạo, một lần nữa, không giống như super.method()truy cập, nó phải là dòng đầu tiên của hàm tạo của bạn. Sau đó, nó rất giống với các hàm this()tạo, DRY (Đừng lặp lại chính bạn), nếu lớp bạn mở rộng có một hàm tạo thực hiện một số điều bạn muốn thì hãy sử dụng nó và sau đó tiếp tục xây dựng đối tượng của bạn, ví dụ:

YourClass extends MyClass
{
YourClass(arg1, arg2, arg3)
{
super(arg1, arg2) // calls MyClass(arg1, arg2)
validate and process arg3…
}
}

Thông tin thêm:

Ngay cả khi bạn không nhìn thấy nó, hàm tạo không đối số mặc định luôn gọi super()trước. Thí dụ:

MyClass()
{
}

tương đương với

MyClass()
{
super();
}

Tôi thấy rằng nhiều người đã đề cập đến việc sử dụng thisvà supertừ khóa trên các phương pháp và biến – tất cả đều tốt. Chỉ cần nhớ rằng các hàm tạo có các hạn chế duy nhất về cách sử dụng của chúng, đáng chú ý nhất là chúng phải là lệnh đầu tiên của hàm tạo đã khai báo và bạn chỉ có thể sử dụng một.

Từ khóa super trong Java được sử dụng trong lớp con (subclass) để truy cập các thành phần trong lớp cha (superclass):

    • Giúp gọi phương thức của lớp cha được ghi đè (overriding) trong lớp con
    • Giúp truy cập các thuộc tính của lớp cha nếu cả lớp con và lớp cha có các thuộc tính giống tên nhau
    • Giúp gọi hàm khởi tạo có tham số hoặc không có tham số của lớp cha

Khi lớp con gọi phương thức được ghi đè (overriding) có cùng tên với phương thức của lớp cha thì phương thức được gọi đó là của lớp con.

class LopCha{
protected void xuat(){
System.out.println(“Lop cha.”);
}
}
class LopCon extends LopCha{
@Override
public void xuat(){
System.out.println(“Lop con.”);
}
}
public class Test{
public static void main(String[] args) {
LopCon aaa = new LopCon();
aaa.xuat();
}
}

Kết quả

Lop con.

Chúng ta có thể gọi phương thức của lớp cha trong lớp con sau khi đã ghi đè (overriding) phương thức đó bằng cách sử dụng từ khóa super.

class LopCha{
public void xuat(){
System.out.println(“Lop cha.”);
}
}
class LopCon extends LopCha{
@Override
public void xuat(){
super.xuat();//gọi hàm xuat() của lớp cha
System.out.println(“Lop con.”);
}
}
public class Test{
public static void main(String[] args) {
LopCon aaa = new LopCon();
aaa.xuat();
}
}

Kết quả

Lop cha.
Lop con.

Lớp cha và lớp con có thể có các thuộc tính có tên giống nhau. Chúng ta có thể sử dụng từ khóa super để gọi thuộc tính của lớp cha.

class LopCha{
protected String type=”LopCha.”;
}
class LopCon extends LopCha{
public String type=”LopCon.”;
public void xuat(){
System.out.println(type);
//gọi thuộc tính lớp cha
System.out.println(super.type);
}
}
public class Test{
public static void main(String[] args) {
LopCon aaa = new LopCon();
aaa.xuat();
}
}

Kết quả

LopCon.
LopCha.

Khi một đối tượng của lớp con được tạo ra, hàm khởi tạo mặc định (default constructor) của lớp cha cũng sẽ tự động được gọi. Trong một số trường hợp, chúng ta muốn chọn hàm khởi tạo nào trong lớp cha được gọi thì có thể sử dụng super().

Trong hàm khởi tạo của lớp con, chúng ta có thể gọi hàm khởi tạo của lớp cha bằng super(). super() chỉ có thể được gọi trong hàm khởi tạo của lớp con và phải được đặt ở dòng lệnh đầu tiên trong hàm khởi tạo của lớp con.

class LopCha{
LopCha(){
System.out.println(“LopCha.”);
}
}
class LopCon extends LopCha{
LopCon(){
super();
System.out.println(“LopCon.”);
}
}
public class Test{
public static void main(String[] args) {
LopCon aaa = new LopCon();
}
}

Kết quả

LopCha.
LopCon.

Chúng ta cũng có thể gọi hàm khởi tạo có tham số của lớp cha ở dòng lệnh đầu tiên trong hàm khởi tạo của lớp con sử dụng super().

class LopCha{
LopCha(){
System.out.println(“LopCha.”);
}
LopCha(String type){
System.out.println(type + ” ke thua tu LopCha.”);
}
}
class LopCon extends LopCha{
LopCon(){
super(“LopCon”);
System.out.println(“LopCon.”);
}
}
public class Test{
public static void main(String[] args) {
LopCon aaa = new LopCon();
}
}

Kết quả

LopCon ke thua tu LopCha.
LopCon.

Lưu ý: Nếu đã gọi hàm khởi tạo có tham số của lớp cha trong lớp con thì hàm khởi tạo mặc định của lớp cha sẽ không được trình biên dịch tự gọi nữa.

Bài trước và bài sau trong môn học