Pattern matching là một tính năng chính trong phát triển phần mềm.Trong khi pattern matching áp dụng ở một số địa điểm, việc sử dụng hiện tại của nó được giới hạn ở Tôi muốn so sánh sức mạnh của các mô hình phù hợp trên một vài ngôn ngữ lập trình mà tôi quen thuộc trong bài viết này. switch case Tôi cho rằng mỗi độc giả đều quen thuộc với Syntax được thừa hưởng từ C. Tóm lại: switch case Các điều khoản switch tham chiếu đến một tuyên bố trả về giá trị. Mỗi câu lệnh trường hợp đặt một câu lệnh khác; nếu giá trị khớp với câu lệnh, nó thực hiện khối liên quan. trường hợp các điều khoản được đánh giá theo thứ tự. điều khoản đầu tiên phù hợp nhận được khối của nó được thực hiện. Trong C, các điều khoản trường hợp là thâm nhập; bạn cần phải phá vỡ rõ ràng để thoát khỏi chuyển đổi, nếu không, trường hợp tiếp theo được đánh giá Cấu hình Java Pattern Matching Tôi sẽ bắt đầu với Java, vì nó là ngôn ngữ lập trình đầu tiên tôi sử dụng trong bối cảnh chuyên nghiệp. Mẫu phù hợp của Java đã phát triển rất nhiều trên các phiên bản của nó. Đây là mẫu "chính thức" cho phiên bản 23, được sửa đổi một chút. thực hiện và a phương pháp để đánh giá phạm vi của nó. nó chắc chắn Một ví dụ điển hình về lập trình hướng đối tượng. Shape static not interface Shape { } record Rectangle(double length, double width) implements Shape { } record Circle(double radius) implements Shape { } public class Main { static double getPerimeter(Shape s) throws IllegalArgumentException { return switch (s) { //1 case Rectangle r when r.length() == r.width() -> { //2 System.out.println("Square detected"); yield 4 * r.length(); } case Rectangle r -> //3 2 * r.length() + 2 * r.width(); case Circle c -> //4 2 * c.radius() * Math.PI; default -> //5 throw new IllegalArgumentException("Unrecognized shape"); }; } } Reference the Shape parameter as s tham chiếu Shape parameter as s Đánh giá xem s là hình chữ nhật hay không và liệu hình chữ nhật có phải là hình vuông hay không. Xác định xem s có phải là một hình chữ nhật Xác định xem s có phải là một vòng tròn Nếu không có các điều khoản trước phù hợp, mặc định để ném một ngoại lệ Phiên bản Java này sẽ là cơ sở của chúng tôi. Đặc điểm của New Syntax switch Chuyển đổi Lời bài hát: The New Syntax Has Some Advantages Over the Legacy Non-Arrow được thừa kế từ c. switch C phong cách Lời bài hát: Once The Runtime Has Executed A Block, nó chạy tiếp theo để ngăn chặn nó, bạn cần thiết lập một Trong những ngày cũ không tốt như vậy, một số nhà phát triển đã tận dụng tính năng này để tránh trùng lặp mã. case case case break Tuy nhiên, kinh nghiệm đã chỉ ra rằng nó là quá nhiều nguyên nhân của các lỗi tiềm năng: thực tiễn mã hóa hiện đại có xu hướng tránh nó. Với phông chữ mũi tên mới, runtime chỉ đánh giá tương ứng Block rồi. break case C phong cách Các điều khoản chỉ đánh giá các giá trị đơn giản. Cộng đồng đã tôn vinh Java 7 như một phần thưởng lớn khi nó cho phép các giá trị String. Java 21 đã đi xa hơn nữa: kết hợp với phác thảo mũi tên, nó cho phép chuyển đổi các loại. Trong ví dụ trên, chúng tôi kiểm tra chính xác Loại case Shape Ngoài ra, nếu thay đổi lớp học Nếu hệ thống phân cấp lớp là , trình biên dịch có thể tự động phát hiện các trường hợp bị thiếu. Cuối cùng, phiên bản 24 đã thêm tùy chọn bổ sung Bộ lọc và sealed when Ở mặt ngược, trong ngữ pháp C cũ, thời gian chạy nhảy trực tiếp vào đúng Thuật ngữ mũi tên mới đánh giá chúng theo thứ tự, giống như nếu với Các tuyên bố case if else Trong các phần tiếp theo, chúng tôi sẽ chuyển mã sang các ngôn ngữ khác. Mô hình Scala Matching Mẫu phù hợp của Scala đã được thứ hai cho không ai kể từ khi thành lập. Kotlin lấy rất nhiều cảm hứng từ nó. trait Shape case class Rectangle(length: Double, width: Double) extends Shape case class Circle(radius: Double) extends Shape def getPerimeter(s: Shape) = { s match { //1 case Rectangle(length, width) if length == width => //2-3 println("Square detected") 4 * length case Rectangle(length, width) => 2 * length + 2 * width //3-4 case Circle(radius) => 2 * radius * Math.PI //3-5 case _ => throw new IllegalArgumentException("Unrecognized shape") //6 } } Sử dụng s reference trực tiếp Đánh giá xem s là hình chữ nhật hay không và liệu hình chữ nhật có phải là hình vuông hay không. Scala bổ sung khớp với các thuộc tính lớp Xác định xem s có phải là một hình chữ nhật Xác định xem s có phải là một vòng tròn Nếu không có các điều khoản trước phù hợp, mặc định để ném một ngoại lệ Mô hình Kotlin's Pattern Matching Chúng ta hãy dịch mã Java sang Kotlin. kích hoạt the Các tính năng được mô tả trong . phải Thí nghiệm Xwhen-guards Lời bài hát: Keep-371 interface Shape data class Rectangle(val length: Double, val width: Double): Shape data class Circle(val radius: Double): Shape fun getPerimeter(s: Shape) = when (s) { //1 is Rectangle if s.length == s.width -> { //2 println("Square detected") 4 * s.length } is Rectangle -> 2 * s.length + 2 * s.width //3 is Circle -> 2 * s.radius * Math.PI //4 else -> throw IllegalArgumentException("Unknown shape") //5 } } Reference the Shape parameter as s tham chiếu Shape parameter as s Đánh giá xem s là một hình chữ nhật và nếu chiều rộng của hình chữ nhật bằng chiều cao của nó Xác định xem s có phải là một hình chữ nhật Xác định xem s có phải là một vòng tròn Nếu không có các điều khoản trước phù hợp, mặc định để ném một ngoại lệ Mẫu kết hợp của Kotlin rất giống với Java, với những thay đổi nhỏ trong phông chữ. , Thay thế . e.g if when Sự tiến hóa so sánh của Kotlin so với Java trong phù hợp mô hình khá sáng tỏ. Java bị bỏ lại phía sau phác thảo C truyền thống, trong khi Kotlin đã có thể phù hợp trên các loại bê tông ngay từ đầu. Vào năm 2020, Java 14 đã giảm khoảng cách với nhà khai thác mũi tên; một năm sau đó, Java 16 đã đóng khoảng cách hoàn toàn với khả năng phù hợp trên các loại bê tông. Điều khoản when Bản chất thực nghiệm của Kotlin có nghĩa là Java đã vượt qua Java – ít nhất là trong lĩnh vực này! if Mô hình Python Matching Trước đó, Python không cung cấp bất cứ điều gì tương tự như Tuyên bố của các ngôn ngữ JVM trên. Từ phiên bản 3.10, nó cung cấp cùng một khả năng theo một cách thanh lịch: switch class Shape: pass class Rectangle(Shape): def __init__(self, length: float, width: float): self.length = length self.width = width class Circle(Shape): def __init__(self, radius: float): self.radius = radius def get_perimeter(s: Shape) -> float: match s: case Rectangle(length=l, width=w) if l == w: print("Square detected") return 4 * l case Rectangle(length=l, width=w): return 2 * l + 2 * w case Circle(radius=r): return 2 * pi * r case _: raise ValueError("Unknown shape") Runtime đánh giá các điều khoản theo thứ tự, như trong các ngôn ngữ JVM. case Mô hình Rust's Pattern Matching Cách tiếp cận của Rust đối với quản lý bộ nhớ không hoạt động tốt với các loại kiểm tra.Tóm lại, Rust cung cấp hai khái niệm cơ bản: Các cấu trúc là người giữ vị trí dữ liệu có cấu trúc; kích thước bộ nhớ của chúng được biết đến tại thời điểm biên soạn Tính năng là hợp đồng, tương tự như giao diện Bạn có thể cung cấp một thực hiện của một tính năng cho một cấu trúc Kể từ khi tham chiếu có thể chỉ đến các cấu trúc có kích cỡ khác nhau, trình biên dịch không thể biết kích cỡ của nó tại thời điểm biên dịch và phải đặt biến trên đống thay vì đống. Tôi đã cố gắng chuyển mã gốc sang Rust one-to-one cho mục đích giáo dục. Java gốc không tận dụng lợi thế của polymorphism; nó không phải là tuyệt vời. Trong Rust, nó thậm chí còn tồi tệ hơn. Thật thú vị khi nhận ra rằng trong khi Rust không phải là một ngôn ngữ lập trình hướng đối tượng, nó dẫn bạn đến sử dụng polymorphism. Cảnh báo: Tôi không đề nghị mã sau đây và sẽ phủ nhận bất kỳ liên kết nào với nó! trait Shape: Any { fn as_any(&self) -> &dyn Any; //1 } struct Circle { radius: f64, } struct Rectangle { width: f64, height: f64, } impl Shape for Circle { fn as_any(&self) -> &dyn Any { //2 self } } impl Shape for Rectangle { fn as_any(&self) -> &dyn Any { //2 self } } fn get_perimeter(s: Box<dyn Shape>) -> f64 { match s.as_any() { //3 any if any.is::<Rectangle>() => { //4 let rectangle = any.downcast_ref::<Rectangle>().unwrap(); //5 if rectangle.width == rectangle.height { println!("Square matched"); 4.0 * rectangle.width } else { 2.0 * (rectangle.width + rectangle.height) } } any if any.is::<Circle>() => { //4 let circle = any.downcast_ref::<Circle>().unwrap(); //5 2.0 * std::f64::consts::PI * circle.radius } _ => panic!() } } Hệ thống kiểu của Rust không cung cấp một cách để có được kiểu của một biến. chúng ta phải tạo ra một hàm dành riêng cho điều đó. Thực hiện chức năng cho các cấu trúc Trận đấu trên kiểu cấu trúc cơ bản Kiểm tra loại Tải xuống cấu trúc cơ bản để sử dụng các trường của nó Cổng mã nhân tạo này ở trên miêu tả sai khả năng khớp mô hình của Rust. . Nhiều địa điểm Kết luận Trong số tất cả các ngôn ngữ được mô tả trong bài viết, Scala là người đầu tiên cung cấp mô hình phù hợp trong Trong nhiều năm, đó là Grail mà những người khác đã cố gắng nắm bắt; Kotlin và Java cuối cùng đã đạt đến giai đoạn này. switch Ngoài JVM, Python và Rust có khả năng khớp mô hình mạnh mẽ. Với phá cấu trúc, phù hợp mô hình là một trợ giúp lớn cho các nhà phát triển muốn viết mã có thể đọc và duy trì. Mã nguồn đầy đủ cho bài viết này có thể được tìm thấy tại . trên github To go further: Cấu hình trong Java 23 Mô hình phù hợp tại Kotlin Mô hình phù hợp với Scala Tuyên bố trận đấu trong Python Mô hình phù hợp trong Rust Ban đầu được xuất bản tại A Java Geek vào ngày 20 tháng 7 năm 2025 Tên Java Geek