Trong lập trình việc xác định và định nghĩa các kiểu dữ liệu, chú thích đầu vào cho các class, method là điều cần thiết mà gần như hầu hết các ngôn ngữ lập trình đều không thể thiếu. Trong grooy cũng vậy, hôm nay chúng ta sẽ cùng tìm hiểu về Generics, Traits, Annotations trong Groovy.
Tìm hiểu về Generics - Traits - Annotations trong Groovy

Generics
Generics cho phép các type (classes and interfaces) trở thành parameters khi định nghĩa classes, interface vs method. Type parameters cung cấp cách để bạn sử dụng lại cùng một mã với các đầu vào khác nhau. Sự khác biệt là đầu vào của parameter chính là value, trong khi đầu vào của type parameter là types.
Generic for Collections
Các collections classes giống như List class có thể được khái quát hóa để chỉ các collections thuộc loại đó mới được chấp nhận trong application. Một ví dụ về ArrayList tổng quát được hiển thị bên dưới.
List<String> list = new ArrayList<String>();
Với mã sau đây, tôi đang thực hiện các nhiệm vụ sau:
- Tạo bộ sưu tập ArrayList tổng quát sẽ chỉ chứa Strings.
- Thêm 3 string vào list.
- Đối với mỗi mục trong list, in giá trị của strings.
class Example {
static void main(String[] args) {
// Creating a generic List collection
List<String> list = new ArrayList<String>();
list.add("First String");
list.add("Second String");
list.add("Third String");
for(String str : list) {
println(str);
}
}
}
Đầu ra của chương trình trên sẽ là -
First String
Second String
Third String
Generalized Classes
Toàn entire class cũng có thể được generalized. Điều này làm cho class linh hoạt hơn trong việc chấp nhận bất kỳ loại nào và làm việc tương ứng với các loại đó. Hãy xem một ví dụ về cách chúng ta có thể thực hiện được điều này.
- Tôi đang tạo một class có tên ListType. Lưu ý các từ khóa <T> được đặt ở phía trước định nghĩa class. Điều này cho trình biên dịch biết rằng class này có thể chấp nhận bất kỳ loại nào. Vì vậy, khi chúng ta khai báo một đối tượng của class này, chúng ta có thể chỉ định một loại trong quá trình khai báo và loại đó sẽ được thay thế trong phần <T>
- Generic class có các phương thức getter và setter đơn giản để làm việc với biến member được xác định trong class.
- Trong main program, lưu ý rằng chúng ta có thể khai báo các đối tượng của lớp ListType, nhưng thuộc các kiểu khác nhau. Cái đầu tiên là kiểu Integer và cái thứ hai là kiểu String.
class Example {
static void main(String[] args) {
// Creating a generic List collection
ListType<String> lststr = new ListType<>();
lststr.set("First String");
println(lststr.get());
ListType<Integer> lstint = new ListType<>();
lstint.set(1);
println(lstint.get());
}
}
public class ListType<T> {
private T localt;
public T get() {
return this.localt;
}
public void set(T plocal) {
this.localt = plocal;
}
}
Kết quả sẽ là
First String
1
Traits
Traits là một đặc điểm của ngôn ngữ cấu trúc cho phép:
- Định nghĩa thành phần của behavior.
- Triển khai các interface trong thời gian chạy.
- Khả năng tương thích với static type checking/compilation việc (kiểm tra/biên dịch kiểu tĩnh)
Chúng có thể được coi là các interface mang cả implementations vs state. Một trait được xác định bằng từ khóa trait.
trait Marks {
void DisplayMarks() {
println("Display Marks");
}
}
Sau đó, người ta có thể sử dụng từ khóa implement để triển khai trait theo cách tương tự như interfaces.
class Example {
static void main(String[] args) {
Student st = new Student();
st.StudentID = 1;
st.Marks1 = 10;
println(st.DisplayMarks());
}
}
trait Marks {
void DisplayMarks() {
println("Display Marks");
}
}
class Student implements Marks {
int StudentID
int Marks1;
}
Implementing Interfaces
Traits có thể triển khai các interface, trong trường hợp đó các interface được khai báo bằng từ khóa implements.
Trong ví dụ sau đây, những điểm chính sau đây sẽ được thực hiện:
- Một interface Total được xác định bằng phương thức DisplayTotal.
- Đặc điểm Marks triển khai interface Total và do đó cần cung cấp cách triển khai cho phương thức DisplayTotal.
class Example {
static void main(String[] args) {
Student st = new Student();
st.StudentID = 1;
st.Marks1 = 10;
println(st.DisplayMarks());
println(st.DisplayTotal());
}
}
interface Total {
void DisplayTotal()
}
trait Marks implements Total {
void DisplayMarks() {
println("Display Marks");
}
void DisplayTotal() {
println("Display Total");
}
}
class Student implements Marks {
int StudentID
int Marks1;
}
Kết quả của chương trình trên sẽ là
Display Marks
Display Total
Properties
Một trait có thể định nghĩa các properties. Một ví dụ về một trait với một property được đưa ra dưới đây.
class Example {
static void main(String[] args) {
Student st = new Student();
st.StudentID = 1;
println(st.DisplayMarks());
println(st.DisplayTotal());
}
interface Total {
void DisplayTotal()
}
trait Marks implements Total {
int Marks1;
void DisplayMarks() {
this.Marks1 = 10;
println(this.Marks1);
}
void DisplayTotal() {
println("Display Total");
}
}
class Student implements Marks {
int StudentID
}
}
Kết quả của chương trình trên là
10
Display Total
Composition of Behaviors
Traits có thể được sử dụng để triển khai đa kế thừa một cách có kiểm soát, tránh diamond issue. Trong ví dụ về mã sau đây, tôi đã xác định hai đặc điểm – Marks vs Total. Class Student sẽ thực hiện cả hai traits. Vì lớp Student mở rộng cả hai traits nên nó có thể truy cập cả hai phương thức – DisplayMarks và DisplayTotal.
class Example {
static void main(String[] args) {
Student st = new Student();
st.StudentID = 1;
println(st.DisplayMarks());
println(st.DisplayTotal());
}
}
trait Marks {
void DisplayMarks() {
println("Marks1");
}
}
trait Total {
void DisplayTotal() {
println("Total");
}
}
class Student implements Marks,Total {
int StudentID
}
Total
Marks1
Extending Traits
Traits có thể mở rộng từ một trait khác, trong trường hợp đó bạn phải sử dụng từ khóa extends. Trong ví dụ về mã sau đây, chúng tôi đang mở rộng Total bằng Marks.
class Example {
static void main(String[] args) {
Student st = new Student();
st.StudentID = 1;
println(st.DisplayMarks());
}
}
trait Marks {
void DisplayMarks() {
println("Marks1");
}
}
trait Total extends Marks {
void DisplayMarks() {
println("Total");
}
}
class Student implements Total {
int StudentID
}
Total
Annotations
Annotations là một dạng siêu dữ liệu trong đó chúng cung cấp dữ liệu về một chương trình không phải là một phần của chương trình đó. Annotations không có ảnh hưởng trực tiếp đến hoạt động của mã mà chúng chú thích.
Information for the compiler − Trình biên dịch có thể sử dụng các chú thích để phát hiện lỗi hoặc ngăn chặn các cảnh báo.
Compile-time and deployment-time processing − Các công cụ phần mềm có thể xử lý thông tin chú thích để tạo mã, tệp XML, v.v.
Runtime processing − Một số annotation có sẵn để kiểm tra trong thời gian chạy.
Trong Groovy, một annotation cơ bản trông như sau −
@interface - Ký tự tại dấu (@) cho trình biên dịch biết phần tiếp theo là annotation
Annotations có thể xác định các thành viên ở dạng phương thức không có nội dung và giá trị mặc định tùy chọn.
Annotations có thể được áp dụng cho các loại sau -
String Type
@interface Simple {
String str1() default "HelloWorld";
}Enum type
enum DayOfWeek { mon, tue, wed, thu, fri, sat, sun }
@interface Scheduled {
DayOfWeek dayOfWeek()
} Class type
@interface Simple {}
@Simple
class User {
String username
int age
}
def user = new User(username: "Joe",age:1);
println(user.age);
println(user.username);Annotation Member Values
@interface Example {
int status()
}
@Example(status = 1)Closure Annotation Parameters
@interface OnlyIf {
Class value()
}
@OnlyIf({ number<=6 })
void Version6() {
result << 'Number greater than 6'
}
@OnlyIf({ number>=6 })
void Version7() {
result << 'Number greater than 6'
}Meta Annotations
Đây là một tính năng khá hữu ích của các chú thích trong Groovy. Đôi khi bạn có thể có nhiều chú thích cho một phương thức như phương thức được hiển thị bên dưới. Đôi khi điều này có thể trở nên lộn xộn khi có nhiều chú thích.
@Procedure
@Master class
MyMasterProcedure {}
Trong trường hợp như vậy, bạn có thể xác định một meta annotations kết hợp nhiều chú thích lại với nhau và áp dụng meta annotations cho method. Vì vậy, với ví dụ trên, bạn có thể xác định rõ ràng bộ sưu tập chú thích bằng cách sử dụng AnnotationCollector.
import groovy.transform.AnnotationCollector
@Procedure
@Master
@AnnotationCollector
Khi việc này hoàn tất, bạn có thể áp dụng meta annotations cho phương thức -
import groovy.transform.AnnotationCollector
@Procedure
@Master
@AnnotationCollector
@MasterProcedure
class MyMasterProcedure {}
Bài tiếp theo: Bài 15 - Hướng dẫn lập trình groovy: Closures
Không có nhận xét nào: