2013-03-02 35 views
10

Hãy nói rằng tôi có đoạn mã này:Inheritance: đối tượng tạo

class Animal { 
    int legs = 4; 
    int head = 1; 
} 

public class Dog extends Animal { 
    public static void main (String []args) { 
     Dog dog = new Dog(); 
    } 
} 

Tôi nhận thức được super() ngầm đặt trong dòng đầu tiên của các nhà xây dựng không args, vì vậy tôi biết rằng các nhà xây dựng Animal sẽ được thực hiện và do đó biến thể hiện của Animal sẽ được thiết lập.

Với mục đích này, tôi muốn hiểu nếu một khi các biến đó được khởi tạo bởi hàm tạo siêu (Animal), biến mẫu đó sẽ được giữ trong đối tượng Động vật hoặc sao chép vào phân lớp (Dog).

Trong trường hợp đầu tiên một đối tượng Animal sẽ được khởi tạo ngầm bởi super(); và bất cứ khi nào dụ Dog sẽ cần phải truy cập vào một trong những biến nó sẽ được thực hiện truy cập vào các biến lưu giữ trong trường hợp Animal (tạo ra trên nền). Hoặc trường hợp thứ hai, nếu đối tượng Động vật sẽ được tạo tạm thời, tất cả biến cá thể (trong Animal) được sao chép vào cá thể Dog và sau đó xóa cá thể của Animal tạm thời được tạo.

Cá nhân tôi nghĩ rằng ví dụ: đối tượng Dog sẽ được liên kết trực tiếp với đối tượng Animal được kết nối trực tiếp với đối tượng.

Có theo cách này không?

Trả lời

16

Chỉ có một đối tượng, ngay lập tức (ngay từ đầu) một ví dụ Dog. Nó có tất cả các trường của Dog (không phải bạn có bất kỳ ở đây) tất cả các trường của Animal.

Ban đầu tất cả các biến sẽ được đặt thành giá trị mặc định của chúng (0, null, v.v.). Sau đó, khi bạn đến cơ thể của mỗi lớp (sau khi gọi hàm tạo của lớp bậc trên), các biến khởi tạo biến thể hiện được thực thi, thì phần thân của hàm tạo cho lớp đó được thi hành.

Không cần sao chép vì chỉ có một đối tượng. Vì vậy, ví dụ, nếu bạn đã viết một constructor Animal như thế này:

public Animal() { 
    System.out.println(this.getClass()); 
} 

... nó sẽ in ra Dog, vì đối tượng đã là một Dog, mặc dù constructor Dog của nó sẽ không được thực hiện chưa.

+2

Bạn đang làm việc đó như thế nào? – bsiamionau

+2

@zvzdhk Bởi vì đối tượng chính nó là một 'Dog'. Ngay cả trong hàm khởi tạo (và cũng trong hàm tạo 'super')' this' chỉ đối tượng hiện tại. Vì vậy, nó có thể trông lạ, nhưng nó khá đơn giản. – gaborsch

+6

@GaborSch: Tôi nghĩ * zvzdhk có thể đã đề cập đến tốc độ phản hồi, thay vì đặt câu hỏi kỹ thuật. Tôi có thể sai, tất nhiên. –

2

khi các biến đã được khởi tạo bởi các siêu constructor (Animal), những instance variable sẽ được giữ ở đó trong đối tượng Animal hoặc sao chép vào lớp con (Chó).

Thứ nhất, các biến mẫu là không được ghi đè trong sub-class. họ chỉ có hiển thị. Chúng sẽ không được sao chép trong ví dụ của Dog. Bạn có thể truy cập chúng từ lớp Dog với cá thể Dog nếu chúng được đánh dấu là public, protected hoặc no-modifier

+0

Vì vậy, được liên kết với nhau như tôi nghĩ? Có bao nhiêu đồ vật được tạo ra cuối cùng? – Rollerball

+0

@Rollerball như John skeet đã trả lời nó, sẽ chỉ có một đối tượng được tạo ra (đối tượng Dog) :) – PermGenError

1

Không có đối tượng động vật, chỉ có một đối tượng Dog sẽ được tạo.Đối tượng Dog có các biến chân, đầu được thừa kế từ đối tượng Động vật. Họ sẽ hành động như thể các thành viên của đối tượng Dog. Lớp khởi tạo của lớp động vật sẽ được gọi kể từ khi bạn mở rộng lớp Animal trong Dog.And vì Animal ngầm mở rộng Object, lớp khởi tạo lớp Object sẽ được gọi từ Animal.

Cách Java xử lý các cuộc gọi này là nội bộ với Java và có thể thay đổi từ phiên bản sang phiên bản nhưng hành vi bạn nên giữ nguyên.

9

bạn Dog kéo dài Animal, và head, legs biến là không tin, vì vậy bạn sẽ truy cập chúng từ Dog dụ.

Trên thực tế, những điều sau đây sẽ xảy ra:

  • Bạn tạo một đối tượng Dog, đó cũng là một Animal
  • tất cả các thuộc tính đối tượng được tạo ra và khởi tạo (bao gồm cả head, và sau khi các thuộc tính của Animal như tốt)
  • Hàm tạo ẩn của Dog được gọi (gọi là super())
  • Điểm yếu ngầm tructor của Animal được gọi

Và kết quả là một đối tượng, mà là một Dog, nhưng ngầm cũng là một Animal.


Làm thế nào một đối tượng Dog trông giống như (chúng ta hãy quên đi những lớp Object vì lợi ích của ví dụ). Giả sử Dog có thuộc tính public String name;.

Dưới đây là một bản đồ ký ức về một trường hợp Dog:

Addr Type  Name  Defined in: 
------------------------ 
| 0 | int | legs | Animal 
| 1 | int | head | Animal 
| 2 | String | name | Dog 
------------------------ 
  • Nếu bạn có một Animal, bạn truy cập vào head như là một biến tại địa chỉ 1,
  • Nếu bạn có một Dog , bạn truy cập vào name dưới dạng biến số tại địa chỉ 2,
  • Nếu bạn có Dog, bạn truy cập vào head như là một biến tại địa chỉ 1

Mã chạy trong cơ thể của Animal lớp có thể chỉ thấy địa chỉ 0-1. Mã chạy trong lớp Dog có thể truy cập địa chỉ 0-2. Nếu thuộc tính sẽ là private đối với lớp cha, thì địa chỉ đó sẽ bị cấm đối với lớp con.

Bản đồ bộ nhớ này làm cho có thể downcast các đối tượng rất dễ dàng: cùng một bản đồ bộ nhớ được sử dụng, chỉ điều trị (mã và khả năng hiển thị) là khác nhau.

Tôi hy vọng nó làm rõ một chút.

+0

Cập nhật với phần giải thích về cấu trúc đối tượng thừa kế. – gaborsch

+0

tnx rất nhiều! Mọi thứ đều rõ ràng bây giờ! – Rollerball

+0

+1 để biết mô tả đầy đủ –