Các phương thức trừu tượng so với các biến đối tượng cho các đối tượng tái sử dụng


8

Tôi có khá nhiều mã Java mà tôi đang làm việc để được sử dụng lại. Vấn đề là có nhiều phần cụ thể của dự án nên cuối cùng có mức độ khớp nối cao hơn giữa dự án ứng dụng và dự án cơ sở mã.

So sánh với các tình huống sau đây khi chúng ta sử dụng một lớp thực hiện việc sử dụng các phương thức trừu tượng để lấy các tài nguyên ra khỏi lớp con và một trong đó chúng ta chỉ cần khai báo các biến thể hiện.

Các phương pháp trừu tượng:

public abstract class SuperBaseClass {

    public abstract int getNumberOne();
    public abstract String getStringOne();
    public abstract String getStringTwo();

    public printStuff() {
        Log.i("IntAndTwoStrings", String.format("%i %s and %s",
                            getNumberOne(), getStringOne(), getStringTwo()));
    }

}

public class ReusedAppClass extends SuperBaseClass {

    public int getNumberOne() {
        return 1;
    }
    public String getStringOne() {
        return "String1";
    }
    public String getStringTwo() {
        return "String2";
    }

    public ReusedAppClass() {
        printStuff();
    }

}

Biến thể hiện:

public class SuperBaseClass {

    protected int numberOne;
    protected String stringOne;
    protected String stringTwo;

    public printStuff() {
        //Possibly throw RuntimeExceptions if the app didnt set these
        Log.i("IntAndTwoStrings", String.format("%i %s and %s",
                            numberOne, stringOne, stringTwo));
    }

}

public class ReusedAppClass extends SuperBaseClass {

    public ReusedAppClass() {
        numberOne = 1;
        stringOne = "String1";
        stringTwo = "String2";
        printStuff();
    }

}

Có một sự đánh đổi? Là tình huống phương thức trừu tượng quá mức cần thiết, hay đây là những gì các lớp trừu tượng được tạo ra cho?

Câu trả lời:


8

Tôi nghĩ rằng các phương pháp trừu tượng là sự lựa chọn tốt hơn. Nếu việc triển khai các thuộc tính này không phải là điều bạn muốn các lớp con lo lắng, thậm chí bạn có thể muốn lớp cơ sở chịu trách nhiệm về nó, tức là sử dụng các trường riêng trong lớp cơ sở với các bộ truy cập công cộng và bộ biến đổi được bảo vệ:

public class SuperBaseClass {

    private int numberOne;
    private String stringOne;
    private String stringTwo;

    public int getNumberOne() { return numberOne; }
    public String getStringOne() { return stringOne; }
    public String getStringTwo() { return stringTwo; }

    protected void setNumberOne(String numberOne) { this.numberOne = numberOne; }
    protected void setStringOne(String stringOne) { this.stringOne = stringOne; }
    protected void setStringTwo(String stringTwo) { this.stringTwo = stringTwo; }

    public printStuff() {
        Log.i("IntAndTwoStrings", String.format("%i %s and %s", getNumberOne(), getStringOne(), getStringTwo()));
    }
}

Cách tiếp cận này cung cấp đóng gói mạnh, tức là số lượng mã có thể trực tiếp sửa đổi các trường của bạn được giảm thiểu.


Đóng gói tốt hơn là một lợi thế nhất định để sử dụng phương pháp trừu tượng 1
Styler

5

Cách tiếp cận lớp trừu tượng cũng buộc lớp mở rộng "khởi tạo" các biến trong khi với các biến đối tượng được bảo vệ, các mặc định có thể dễ dàng được sử dụng dẫn đến nhầm lẫn / lỗi nếu không được mở rộng.


3

IMHO một cách tiếp cận tốt hơn là sử dụng thành phần và tránh kế thừa hoàn toàn nếu chỉ vì mục đích tùy chỉnh một số trường. Bạn nói "để lấy tài nguyên ra khỏi lớp con", vì vậy hãy làm điều đó:

public class MyResources() {

private int numberOne;
private String stringOne;
private String stringTwo;

public int getNumberOne() {
    return numberOne;
}

public void setNumberOne(int numberOne) {
    this.numberOne = numberOne;
}

public String getStringOne() {
    return stringOne;
}

public void setStringOne(String stringOne) {
    this.stringOne = stringOne;
}

public String getStringTwo() {
    return stringTwo;
}

public void setStringTwo(String stringTwo) {
    this.stringTwo = stringTwo;
}
}

Sau đó khởi tạo các đối tượng MyResource trong các lớp của bạn và tùy chỉnh chúng theo yêu cầu. Nếu bạn vẫn cần phải có một hệ thống phân cấp các lớp, bạn có thể có đối tượng tài nguyên của mình trong lớp cơ sở và kế thừa nó trong các lớp con:

public abstract class SuperBaseClass {

protected MyResources resources;

public SuperBaseClass() {
    resources.setStringOne("Hello");
}

public class ReusedAppClass extends SuperBaseClass {

public ReusedAppClass () {
    super();
    resources.setStringOne("Hi");
}
}

2

Nếu tất cả các biến đó là thuộc tính của lớp cơ sở và trẻ em phụ thuộc đồng nhất vào chúng thì việc khai báo chúng trong cơ sở là phù hợp và thêm get / setters / accessor trừu tượng sẽ là cách cho phép trẻ em xoa bóp dữ liệu khi chúng thấy phù hợp. Điều này không quá mức cần thiết và OOP được thiết kế để thể hiện các loại mối quan hệ này.

Nếu bạn thấy rằng bạn đang tăng quá nhiều loại dữ liệu này cho lớp cơ sở (hoặc dữ liệu này không phổ biến đối với tất cả trẻ em) thì có lẽ đã đến lúc tái cấu trúc lớp cơ sở lớn hơn vào một thùng chứa cho khác, các lớp cơ sở cụ thể hơn để giúp tổ chức logic và mã của bạn. Điều này sẽ phức tạp hơn một chút nhưng cho phép thiết kế sạch hơn và với cách đặt tên tốt sẽ dễ theo dõi hơn.

Trong một trong các trường hợp của tôi, trước tiên bạn phải phân tích chính xác những gì bạn muốn sử dụng lại trước khi thay đổi mọi thứ. Việc tạo một khung có thể tái sử dụng từ mã hiện tại sẽ kết thúc ở một nơi rất khác so với việc sắp xếp lại dữ liệu và hoạt động trên dữ liệu đó để tái sử dụng mô-đun, chẳng hạn.

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.