Theo dõi tất cả các đối tượng của một lớp


9

Tôi chưa quen với lập trình hướng đối tượng và tôi tiếp tục gặp phải vấn đề này. (Tôi đang lập trình bằng Java) Tôi đã hơi lưỡng lự khi hỏi về vấn đề này, vì có vẻ như đây là một vấn đề cơ bản, nhưng tôi không thể tìm thấy bất kỳ thông tin nào về nó, hoặc câu hỏi về nó ở đây, và không ai trong số sách giáo khoa tôi đã đọc (ở cấp độ khá cơ bản) đã chạm vào vấn đề này:

Thường thì tôi cần theo dõi tất cả các đối tượng của một lớp đã được tạo, để lặp qua chúng cho các mục đích khác nhau. Theo cách chúng tôi hiện đang viết chương trình, nhiều đối tượng chỉ được tham chiếu từ các đối tượng khác, có nghĩa là tôi không có mảng hoặc bộ sưu tập nào để tham chiếu tất cả chúng.

Tôi tưởng tượng rằng, vì điều này có vẻ như là một điều rất cần thiết trong OOP, nên có một cách khá thể chế hóa và đơn giản để đi về vấn đề này? Có phải là thông lệ để giữ một danh sách riêng của tất cả các đối tượng của một lớp?

Tôi đã nghĩ về một mảng hoặc bộ sưu tập tĩnh, thông qua hàm tạo của nó, mọi đối tượng mới được tạo sẽ được thêm vào. Tuy nhiên, điều này sẽ không hoạt động với các lớp con, vì các hàm tạo không được kế thừa?

Tôi nhận ra câu hỏi này có thể không có một câu trả lời dễ dàng; Tôi chỉ hy vọng ai đó có thể khai sáng cho tôi một chút về chủ đề này. Tôi cảm thấy như thể tôi đang thiếu một kiến ​​thức trung tâm ở đây.


5
Một ví dụ cụ thể hơn về theo dõi và theo dõi có thể giúp đỡ. Vấn đề này được xử lý theo nhiều cách khác nhau tùy thuộc vào ngữ cảnh, cách chúng được sử dụng, v.v.
JustinC

2
Tôi nghĩ rằng bạn có thể đang tiếp cận vấn đề từ đầu sai. Nó không phải là rất phổ biến để cần một danh sách tất cả các thể hiện của một lớp nhất định và có một trường hợp sẽ gây ra tất cả các loại vấn đề thiết kế (vì bây giờ ngay cả các thể hiện được tạo trong bối cảnh hoàn toàn không liên quan phụ thuộc vào nhau thông qua danh sách này).
tdammers

1
"Lặp lại thông qua chúng cho các mục đích khác nhau" ... chẳng hạn như ...? Nói chung, một đối tượng có một 'chủ sở hữu' (không phải là một thuật ngữ chính thức, hơn nữa chỉ là một tuyên bố về ngữ nghĩa chương trình) và không phải ai khác cũng có 'mục đích khác nhau' với đối tượng.
AakashM

Câu trả lời:


8

Tôi không biết tại sao bạn cần giữ một danh sách tất cả các trường hợp của một lớp.

Điều đó sẽ gây rò rỉ bộ nhớ vì các đối tượng đó sẽ không bao giờ bị loại bỏ, vì danh sách vẫn sẽ tham chiếu đến chúng sau khi không có lớp nào khác.

Nhưng nếu bạn thực sự muốn đi theo con đường đó:

  1. Sử dụng mẫu Factory. Một lớp nhà máy với các phương thức kích hoạt lớp và trả về các đối tượng. Bằng cách đó, bạn có một điểm tập trung để kiểm soát tức thời.
  2. Sử dụng mẫu Singleton để giữ một danh sách hoặc danh sách chứa các thể hiện.
  3. Làm cho nhà máy đặt từng đối tượng của một loại nhất định vào danh sách sau khi tạo chúng.

Nhân tiện: các nhà xây dựng được kế thừa.


Tất nhiên, bạn có thể cung cấp cho nhà máy một phương thức "xử lý" để loại bỏ thể hiện khỏi danh sách các trường hợp được theo dõi. Nhưng không có cách nào để gọi nó một cách rõ ràng. Hoặc cung cấp cho cá thể một phương thức xử lý kích hoạt phương thức xử lý trong nhà máy của nó, có cùng một nhược điểm nhưng có nhiều khả năng được gọi là thực tế hơn khi nó gần với người dùng hơn, dễ nhìn thấy hơn.
jwenting

@jwenting Tất nhiên đó là một cách. Nhưng điều đó sẽ tạo ra sự phụ thuộc xấu xí, không cần thiết giữa các lớp và nhà máy. Các lớp học không nên biết gì về nhà máy tạo ra chúng.
Tulains Córdova

do đó có ca khúc giữ nhà máy của những gì nó tạo ra, chứ không phải là đối tượng nói với các nhà máy để đăng ký nó ...
jwenting

Một singleton về mặt kỹ thuật sẽ giữ tất cả các trường hợp tôi đoán. Một ví dụ duy nhất.
Giàn khoan

3

Cần lưu ý rằng các tham chiếu yếu có thể được sử dụng kết hợp với các giải pháp đã cho khác để cho phép trình thu gom rác xử lý các đối tượng được theo dõi khi chúng không còn được tham chiếu ở nơi khác. Điều này giúp loại bỏ rò rỉ bộ nhớ mà không yêu cầu mã ở nơi khác để xử lý các đối tượng theo cách thủ công hoặc nếu không quan tâm rằng chúng đang được theo dõi. Bạn có thể cung cấp ReferenceQueue để nhận thông báo về các tham chiếu đến các đối tượng đã được giải phóng.

Tôi đã nghĩ về một mảng hoặc bộ sưu tập tĩnh, thông qua hàm tạo của nó, mọi đối tượng mới được tạo sẽ được thêm vào. Tuy nhiên, điều này sẽ không hoạt động với các lớp con, vì các hàm tạo không được kế thừa?

Các constructor của các lớp cơ sở được gọi trước các constructor của các lớp dẫn xuất. Mỗi lớp có ít nhất một hàm tạo và hàm tạo không thể bị ghi đè.


2

Khi làm game, đôi khi người ta muốn có một bộ sưu tập "tự quản lý" của từng loại đối tượng trò chơi.

Một triển khai trông như thế này:

public class Car {

    static ArrayList<Car> list = new ArrayList<Car>();

    public Car() {
        list.add(this);
    }

    void kill() {
        list.remove(this);
    }

    static public void updateAll()
    {
        for (int i = list.size() - 1; i >= 0; i--)
        {
                list.get(i).update();
        }
    }

    public void update()
    {
        //update logic
    }
}

Theo cách này, các phương thức thao tác với bộ sưu tập có thể được khai báo là tĩnh trong khi các phương thức không tĩnh xử lý một thể hiện (update ALL so với update).

Mặc dù tốt cho các kịch bản rất đơn giản, với độ phức tạp thậm chí vừa phải, tốt nhất là thường tạo các lớp trình quản lý riêng biệt.


1
Bạn có thể trực tiếp viết static ArrayList<ListeStatic> list = new ArrayList<ListeStatic>();ans thay thế statc {..}
cl-r

2
Trong phương thức Java, tên bắt đầu bằng một chữ cái viết thường:uptdateAll(){..;}
cl-r

Rất tiếc ... đã được một lúc kể từ khi tôi phát sóng java của mình ở nơi công cộng
Kelly Thomas

@KellyThomas Một chiếc xe tự thêm vào danh sách, họ tự xóa nó khỏi nó. Nghe có vẻ không tự nhiên.
Tulains Córdova

1
@ CayetanoGonçalves là một trường tĩnh, nó là một danh sách được chia sẻ bởi tất cả các trường hợp.
Kelly Thomas

2

Cố gắng suy nghĩ bối cảnh. Khi bạn tạo một đối tượng, bạn làm như vậy trong một bối cảnh nhất định. Ví dụ: nếu trò chơi của bạn là về việc bắn người ngoài hành tinh, ứng dụng của bạn sẽ luôn tạo ra các vật thể Alien mới. Chúng sẽ được hiển thị trong một trường có tên là Space (có thể là lớp đại diện cho UI chính).

Hoàn toàn tự nhiên khi Space có một thuộc tính có tên currentAliens, đó sẽ là một mảng, mà bạn thêm mỗi người ngoài hành tinh mới mà bạn tạo. Nếu bạn muốn cho phép người dùng của mình xé toạc kết cấu không thời gian và tiêu diệt tất cả người ngoài hành tinh cùng một lúc, bạn sẽ lặp lại qua bộ sưu tập đó và phá hủy từng đối tượng.

Nếu bạn muốn có quyền truy cập vào bộ sưu tập người ngoài hành tinh này từ bên trong các phần khác của ứng dụng của bạn (giả sử, từ trang Cài đặt, nơi bạn có thể muốn cho phép người dùng xóa sạch một số loại người ngoài hành tinh trong một cú trượt ngã), bối cảnh Cài đặt của bạn sẽ cần được cấp quyền truy cập vào đối tượng Space.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.