2010-03-03 39 views
38

Tôi đến từ C# nơi điều này dễ dàng và có thể.Biến trừu tượng trong Java?

tôi có mã này:

public abstract class clsAbstractTable { 

    public abstract String TAG; 
    public abstract void init(); 

} 

nhưng Eclipse nói với tôi rằng tôi sử dụng sửa đổi bất hợp pháp.

Tôi có lớp này:

public class clsContactGroups extends clsAbstractTable { 


} 

Tôi muốn biến và phương pháp quy định tại theo cách như vậy, rằng Eclipse để nhắc tôi, tôi có chưa thực hiện trừu tượng biến và phương pháp.

Làm cách nào để xác định lớp trừu tượng của mình vì vậy tôi nên được nhắc triển khai tóm tắt?

EDIT 1

tôi sẽ tạo ra các lớp học khác nhau cho các bảng db khác nhau. Mỗi lớp phải có biến TABLENAME riêng, không có ngoại lệ. Tôi phải chắc chắn rằng biến này là tĩnh mỗi khi tôi tạo một lớp mới mở rộng lớp trừu tượng.

Sau đó, trong lớp trừu tượng, tôi sẽ có một phương thức ví dụ: init();

Nếu trong phương thức init() này tôi gọi TABLENAME, nó sẽ lấy giá trị từ lớp con.

một cái gì đó như thế này cũng nên làm việc ra

String tablename=(clsAbstract)objItem.TABLENAME; 
// where objItem can be any class that extended clsAbstract; 

EDIT 2

Tôi muốn có một hằng số (tĩnh) được xác định trong mỗi lớp có tên của nó được định nghĩa trong trừu tượng.

  • Tôi xác định TABLENAME biến thành trừu tượng nhưng không có giá trị nào được cung cấp.
  • Tôi tạo một clsContactGroups, tôi sẽ được nhắc thực hiện TABLENAME, đây là nơi lấy một số dữ liệu. ví dụ: TABLENAME = "contactgroups";
  • Tôi tạo một clsContacts thứ hai, tôi sẽ được nhắc triển khai TABLENAME, đây là nơi lấy một số dữ liệu. ví dụ: TABLENAME = "liên hệ";
    vv ...
+0

Biến trừu tượng ??? –

+3

Không có điều nào như các biến trừu tượng trong Java. Phương pháp trừu tượng, vâng. – duffymo

+0

biến TAG trong ví dụ của tôi. Tôi muốn được nhắc thực hiện chúng trên các lớp khác. – Pentium10

Trả lời

45

Tôi nghĩ sự nhầm lẫn của bạn là với thuộc tính C# so với trường/biến. Trong C# bạn không thể định nghĩa các trường trừu tượng, ngay cả trong một lớp trừu tượng. Tuy nhiên, bạn có thể xác định thuộc tính trừu tượng vì đây là các phương pháp hiệu quả (ví dụ: được biên dịch thành get_TAG()set_TAG(...)).

Như một số đã nhắc nhở, bạn không bao giờ nên có trường công khai/biến trong lớp học của bạn, ngay cả trong C#. Một số câu trả lời đã gợi ý những gì tôi muốn giới thiệu, nhưng đã không làm cho nó rõ ràng. Bạn nên dịch ý tưởng của mình thành Java dưới dạng thuộc tính JavaBean, sử dụng getTAG(). Sau đó, các lớp con của bạn sẽ phải thực hiện điều này (tôi cũng đã viết một dự án với các lớp bảng làm điều này).

Vì vậy, bạn có thể có một lớp trừu tượng được định nghĩa như thế này ...

public abstract class AbstractTable { 

    public abstract String getTag(); 
    public abstract void init(); 

    ... 
} 

Sau đó, trong bất kỳ lớp con cụ thể bạn sẽ cần phải xác định một biến thức tĩnh (không đổi) và gửi lại rằng từ getTag(), một cái gì đó như thế này:

public class SalesTable extends AbstractTable { 

    private static final String TABLE_NAME = "Sales"; 

    public String getTag() { 
     return TABLE_NAME; 
    } 

    public void init() { 
     ... 
     String tableName = getTag(); 
     ... 
    } 

} 

EDIT:

lĩnh vực

Bạn không có thể ghi đè thừa hưởng (trong C# hoặc Java). Bạn cũng không thể ghi đè lên các thành viên tĩnh, cho dù đó là các trường hoặc phương thức. Vì vậy, đây cũng là giải pháp tốt nhất cho điều đó. Tôi đã thay đổi ví dụ phương thức init của mình ở trên để cho biết cách sử dụng này - một lần nữa, hãy nghĩ về phương thức getXXX làm thuộc tính.

+1

+1 Tôi nghĩ rằng điều này thực sự trả lời câu hỏi của OP, vì tiền đề ban đầu của câu hỏi là sai (rằng C# có thể có các trường trừu tượng) – JonoW

1

Vì không có thi hành một biến nó không thể là trừu tượng;)

-1

Không, Java không hỗ trợ biến trừu tượng. Nó không thực sự làm cho rất nhiều ý nghĩa, một trong hai.

Thay đổi cụ thể đối với "triển khai" của một biến mà bạn mong đợi một lớp con sẽ làm gì?

Khi tôi có biến số abstractString trong lớp cơ sở, lớp phụ sẽ làm gì để làm cho nó không trừu tượng?

+0

Tôi muốn đảm bảo rằng lớp con xác định biến đó. – Pentium10

+0

@ Pentium10: bạn đã nói điều đó, nhưng tại sao? nó sẽ làm tốt những gì? Tại sao không xác định nó trong lớp cơ sở? –

+0

Tôi muốn đưa ra giá trị trong phân lớp. – Pentium10

6

Không có điều nào như các biến trừu tượng trong Java (hoặc C++).

Nếu lớp cha có biến và lớp con mở rộng cấp độ gốc, thì trẻ không cần triển khai biến. Nó chỉ cần truy cập vào thể hiện của cha mẹ. Việc nhận/đặt hoặc truy cập được bảo vệ sẽ thực hiện.

"... vì vậy tôi nên được nhắc triển khai tóm tắt"? Nếu bạn mở rộng một lớp trừu tượng và không triển khai thực hiện một phương thức trừu tượng thì trình biên dịch sẽ cho bạn biết hoặc thực hiện nó hoặc đánh dấu lớp con là trừu tượng. Đó là tất cả những lời nhắc bạn sẽ nhận được.

+0

Tôi muốn đảm bảo rằng lớp con định nghĩa biến đó. Làm thế nào tôi có thể chắc chắn? – Pentium10

+0

@ Pentium10: lợi thế nào sẽ có trên đơn giản là xác định biến trong lớp cơ sở ở nơi đầu tiên? –

+0

Tôi sẽ tạo các lớp khác nhau cho các bảng db khác nhau. Mỗi lớp phải có biến TABLENAME riêng, không có ngoại lệ. Tôi phải chắc chắn rằng các biến này là tĩnh mỗi khi tôi tạo một lớp mới mở rộng lớp trừu tượng. – Pentium10

49

Xác định hàm tạo trong lớp trừu tượng, thiết lập trường sao cho việc triển khai cụ thể theo đặc tả yêu cầu để gọi/ghi đè hàm tạo.

Ví dụ:

public abstract class AbstractTable { 
    protected String name; 

    public AbstractTable(String name) { 
     this.name = name; 
    } 
} 

Khi bạn mở rộng AbstractTable, lớp sẽ không biên dịch cho đến khi bạn thêm một constructor trong đó kêu gọi super("somename").

public class ConcreteTable extends AbstractTable { 
    private static final String NAME = "concreteTable"; 

    public ConcreteTable() { 
     super(NAME); 
    } 
} 

Bằng cách này, người triển khai bắt buộc phải đặt name. Bằng cách này bạn cũng có thể làm (null) kiểm tra trong constructor của lớp trừu tượng để làm cho nó mạnh mẽ hơn. Ví dụ:

public AbstractTable(String name) { 
    if (name == null) throw new NullPointerException("Name may not be null"); 
    this.name = name; 
} 
+0

Đánh bại tôi với nó :) – seanhodges

+0

Tôi cần điều này được thực hiện với các biến tĩnh. Khi biến sẽ tĩnh cho lớp được triển khai, giống như một tablename của lớp. Tôi không muốn truyền tablename cho hàm tạo mỗi lần. – Pentium10

+0

Biến tĩnh được chia sẻ giữa tất cả các phiên bản của lớp. Nếu bạn đặt nó, sau đó nó sẽ được thay đổi/phản ánh trong ** tất cả các trường hợp ** của lớp, * bất kể * của việc thực hiện. Bạn có * thực sự * muốn điều này? Nếu vậy, sau đó tôi thực sự không thấy bất kỳ lợi ích của việc làm cho họ trừu tượng ... Chính xác vì lý do trước đó (ảnh hưởng đến tất cả các trường hợp). Nó cũng không thể về mặt kỹ thuật vì nó vi phạm ý thức hệ OO. Bạn cần phải học Java/OO một lần nữa hoặc để suy nghĩ lại cách tiếp cận/thiết kế của bạn. – BalusC

2

Chỉ cần thêm phương pháp này để các lớp cơ sở

public abstract class clsAbstractTable { 

    public abstract String getTAG(); 
    public abstract void init(); 

} 

Bây giờ mỗi lớp kéo dài các lớp cơ sở (và không muốn trở thành trừu tượng) nên cung cấp một TAG

Bạn cũng có thể đi cùng với câu trả lời của BalusC

+0

Đó không phải là giải pháp. Giải pháp bắt đầu với việc tìm ra những gì OP muốn đạt được. –

+0

Tôi đã chỉnh sửa các câu hỏi của mình, tôi hy vọng nó rõ ràng những gì tôi muốn đạt được. – Pentium10

+1

Tôi nghĩ đây là giải pháp. Ít nhất chỉ có Java cung cấp đáp ứng tất cả các yêu cầu. Mỗi lớp con sẽ phải cung cấp triển khai getTAG có thể trả về một hằng số chuỗi cho lớp con đó. Theo tôi, điều này thậm chí còn tốt hơn là giữ nó xung quanh trong một biến cho mỗi ví dụ như trong mã ban đầu. – PSpeed

2

Điều tốt nhất bạn có thể làm là có bộ truy cập/bộ biến đổi cho biến.
Giống như getTAG()
Bằng cách đó, tất cả các lớp triển khai sẽ phải triển khai chúng.

Lớp trừu tượng được sử dụng để xác định hành vi trừu tượng không phải là dữ liệu.

+0

Vâng, tôi muốn xác định hành vi trừu tượng, ý tôi là xác định tên, sau đó tôi sẽ xử lý dữ liệu ở cấp độ triển khai. – Pentium10

1

Tại sao bạn muốn tất cả các lớp con xác định biến? Nếu mọi lớp con được cho là có nó, chỉ cần định nghĩa nó trong lớp cha. BTW, cho rằng đó là thực hành tốt OOP không để lộ các lĩnh vực nào, câu hỏi của bạn thậm chí còn ít ý nghĩa hơn.

1

Thay đổi mã để:

public abstract class clsAbstractTable { 
    protected String TAG; 
    public abstract void init(); 
} 

public class clsContactGroups extends clsAbstractTable { 
    public String doSomething() { 
    return TAG + "<something else>"; 
    } 
} 

Bằng cách đó, tất cả các lớp người kế thừa lớp này sẽ có biến này. Bạn có thể làm 200 lớp con và mỗi một lớp trong số đó sẽ có biến này.

Lưu ý phụ: không sử dụng CAPS làm tên biến; sự khôn ngoan chung là tất cả các số nhận dạng mũ tham chiếu đến các hằng số, tức là các phần dữ liệu không thể thay đổi.

+0

Khi tôi tạo một Lớp học mới, tôi có được nhắc nhở để xác định TAG cho lớp đó không? – Pentium10

+0

* Như một số đã nhắc nhở, bạn sẽ không bao giờ có các trường/biến công cộng trong các lớp của bạn * - Không có gì sai với các trường 'final final' trong' final final class', chỉ là vấn đề về hương vị. –

+0

Sau khi đọc bản chỉnh sửa thứ hai của OP, tôi tin rằng anh ấy đang tìm kiếm các cơ chế OOP ở cấp lớp, không được Java hỗ trợ. Bạn có thể thực hiện tất cả các OOP mà bạn muốn với các phương thức * instance *, tuy nhiên không phải với các phương thức * class * ('static' trong Java). Bạn sẽ phải (1) sống với thực tế là mọi * instance * sẽ có bản sao của biến đó hoặc (2) tạo HashMap toàn cục để chứa ánh xạ giữa các tên lớp và các giá trị của TAG trên mỗi lớp nền tảng. Cả hai đều không hoàn hảo, nhưng hey, không ai nói Java hiểu tiếng Anh. ;) – dimitarvp

1

Để thêm siêu dữ liệu theo lớp, có thể chú thích có thể là cách chính xác.

Tuy nhiên, bạn không thể thực thi sự hiện diện của chú thích trong giao diện, cũng giống như bạn không thể thực thi các thành viên tĩnh hoặc sự tồn tại của một hàm tạo cụ thể.

+0

Bạn có thể trình bày một ví dụ không? Tôi muốn được quan tâm xem cách hoạt động của nó. – byxor

0

Có 2 cách xác định thuộc tính trừu tượng trong java mà không đánh dấu thuộc tính là trừu tượng.

cách 1: Xác định một constructor tham số trong lớp trừu tượng, một cái gì đó như:

public abstract class clsAbstractTable { 
     private String TAG; 
     public clsAbstractTable (String TAG) { 
      this.TAG= TAG; 
     } 
} 

Khi xác định một constructor parametrized trong một lớp trừu tượng, các lớp con buộc phải xác định nhà thầu và gọi riêng của họ các nhà xây dựng siêu, do đó đi qua của riêng mình TAG.

Cách 2: Xác định tài sản là phương thức getter, một cái gì đó như:

public abstract class clsAbstractTable { 
    public abstract String getTAG(); 
} 

Bằng cách này, giá trị của TAG tài sản được giao cho được xác định bởi mỗi lớp bê tông.

Nguồn: Define an abstract property in java

Các vấn đề liên quan