Changeset 924534e
- Timestamp:
- Feb 28, 2024, 11:59:34 AM (2 months ago)
- Branches:
- master
- Children:
- 1d5e5601
- Parents:
- dc3fbe5
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/jiada_liang_MMath/relatedwork.tex
rdc3fbe5 r924534e 7 7 8 8 \section{Pascal} 9 10 \lstnewenvironment{pascal}[1][]{% necessary 11 \lstset{ 12 language=pascal, 13 escapechar=\$, % LaTeX escape in code 14 moredelim=**[is][\color{red}]{@}{@}, % red highlighting @...@ 15 }% lstset 16 \lstset{#1}% necessary 17 }{} 9 \lstnewenvironment{pascal}[1][]{\lstset{language=pascal,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{} 18 10 19 11 Classic Pascal has the \lstinline[language=pascal]{const} declaration binding a name to a constant literal/expression. … … 42 34 43 35 \section{Ada} 44 45 \lstnewenvironment{ada}[1][]{% necessary 46 \lstset{ 47 language=[2005]Ada, 48 escapechar=\$, % LaTeX escape in code 49 moredelim=**[is][\color{red}]{@}{@}, % red highlighting @...@ 50 literate={'}{\ttfamily'\!}1 % remove '-' literate as comment 51 }% lstset 52 \lstset{#1}% necessary 53 }{} 36 \lstnewenvironment{ada}[1][]{\lstset{language=[2005]Ada,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},literate={'}{\ttfamily'\!}1}\lstset{#1}}{} 54 37 55 38 An Ada enumeration type is an ordered list of constants, called \Newterm{literals} (enumerators). … … 233 216 \section{\CC} 234 217 \label{s:C++RelatedWork} 235 236 \lstnewenvironment{c++}[1][]{% necessary 237 \lstset{ 238 language=[GNU]C++, 239 escapechar=\$, % LaTeX escape in code 240 moredelim=**[is][\color{red}]{@}{@}, % red highlighting @...@ 241 }% lstset 242 \lstset{#1}% necessary 243 }{} 218 \lstnewenvironment{c++}[1][]{\lstset{language=[GNU]C++,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{} 244 219 245 220 \CC is largely backwards compatible with C, so it inherited C's enumerations. … … 303 278 enum class srgb @: signed char@ { Red = -1, Green = 0, Blue = 1 }; 304 279 \end{c++} 305 There is no implicit conversion from the \lstinline[language=c++]{enum class} type and to its type.280 There is no implicit conversion from the \lstinline[language=c++]{enum class} type and to its declared type. 306 281 \begin{c++} 307 282 rgb crgb = rgb::Red; … … 312 287 313 288 \section{C\raisebox{-0.7ex}{\LARGE$^\sharp$}\xspace} % latex bug: cannot use \relsize{2} so use \LARGE 314 315 \lstnewenvironment{csharp}[1][]{% necessary 316 \lstset{ 317 language=[Sharp]C, 318 escapechar=\$, % LaTeX escape in code 319 moredelim=**[is][\color{red}]{@}{@}, % red highlighting @...@ 320 }% lstset 321 \lstset{#1}% necessary 322 }{} 289 \label{s:Csharp} 290 \lstnewenvironment{csharp}[1][]{\lstset{language=[Sharp]C,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{} 323 291 324 292 % https://www.tutorialsteacher.com/codeeditor?cid=cs-mk8Ojx … … 326 294 \Csharp is a dynamically-typed programming-language with a scoped, integral enumeration-type similar to C/\CC enumeration. 327 295 \begin{csharp} 328 enum Weekday : byte { Mon day, Tuesday, Wednesday, Thursday@ = 10@, Friday, Saturday, Sunday@,@ };296 enum Weekday : byte { Mon, Tue, Wed, Thu@ = 10@, Fri, Sat, Sun@,@ }; 329 297 \end{csharp} 330 298 The default underlying type is @int@, with auto-incrementing, implicit/explicit initialization, terminator comma, and optional integral typing (default @int@) … … 332 300 As well, there is an explicit bidirectional conversion between an enumeration and its integral type, and an implicit conversion to the enumerator label in display contexts. 333 301 \begin{csharp} 334 int day = (int)Weekday.Fri day;$\C{// day == 10}$335 Weekday weekday = (Weekdays)42; $\C{// weekday == 42}$336 Console.WriteLine( Weekday.Fri day ); $\C{// print Friday}$337 string mon = Weekday.Mon day.ToString();302 int day = (int)Weekday.Fri; $\C{// day == 10}$ 303 Weekday weekday = (Weekdays)42; $\C{// weekday == 42, logically invalid}$ 304 Console.WriteLine( Weekday.Fri ); $\C{// print Fri}$ 305 string mon = Weekday.Mon.ToString(); $\C{// mon == "Mon"}$ 338 306 \end{csharp} 339 307 … … 348 316 \begin{csharp} 349 317 @[Flags]@ public enum Weekday { 350 None = 0x0, Mon day = 0x1, Tuesday = 0x2, Wednesday= 0x4,351 Thu rsday = 0x8, Friday = 0x10, Saturday = 0x20, Sunday= 0x40,352 Weekend = @Sat urday | Sunday@,353 Weekdays = @Mon day | Tuesday | Wednesday | Thursday | Friday@354 } 355 Weekday meetings = @Weekday.Mon day | Weekday.Wednesday@; // 0x5318 None = 0x0, Mon = 0x1, Tue = 0x2, Wed = 0x4, 319 Thu = 0x8, Fri = 0x10, Sat = 0x20, Sun = 0x40, 320 Weekend = @Sat | Sun@, 321 Weekdays = @Mon | Tue | Wed | Thu | Fri@ 322 } 323 Weekday meetings = @Weekday.Mon | Weekday.Wed@; // 0x5 356 324 \end{csharp} 357 325 358 \Csharp supports an enumeration class to embed enumeration operations, where the enumerators are objects. 326 \VRef[Figure]{CsharpFreeVersusClass} shows an enumeration with free routines for manipulation, and embedding the enumeration and operations into an enumeration class. 327 The key observation is that an enumeration class is just a structuring mechanism without any additional semantics. 328 329 % https://learn.microsoft.com/en-us/dotnet/api/system.enum?view=net-8.0 330 331 \begin{figure} 332 \centering 333 \lstDeleteShortInline@ 334 \begin{tabular}{@{}l|l@{}} 335 \multicolumn{1}{@{}c|}{non-object oriented} & \multicolumn{1}{c@{}}{object oriented} \\ 336 \hline 359 337 \begin{csharp} 360 public class PaymentType : Enumeration { 361 public static readonly PaymentType DebitCard = new PaymentType(0); 362 public static readonly PaymentType CreditCard = new PaymentType(1); 363 private PaymentType(int value, [CallerMemberName] string name = null) : base(value, name) { } 338 public class Program { 339 340 enum Weekday { 341 Mon, Tue, Wed, Thu, Fri, Sat, Sun }; 342 343 344 static bool isWeekday( Weekday wd ) { 345 return Weekday.Mon <= wd 346 && wd <= Weekday.Fri; 347 } 348 static bool isWeekend( Weekday wd ) { 349 return Weekday.Sat <= wd 350 && wd <= Weekday.Sun; 351 } 352 353 354 public static void Main() { 355 Weekday day = Weekday.Sat; 356 357 Console.WriteLine( isWeekday( day ) ); 358 Console.WriteLine( isWeekend( day ) ); 359 } 364 360 } 365 361 \end{csharp} 366 Find a meaningful example and test it. 362 & 363 \begin{csharp} 364 public class Program { 365 public @class@ WeekDay { 366 public enum Weekday { 367 Mon=-4, Tue=-3, Wed=-2, Thu=-1, 368 Fri=0, Sat=1, Sun=2 }; 369 Weekday day; 370 public bool isWeekday() { 371 return day <= 0; 372 373 } 374 public bool isWeekend() { 375 return day > 0 376 377 } 378 public WeekDay( Weekday d ) { day = d; } 379 } 380 public static void Main() { 381 WeekDay cday = new 382 WeekDay( WeekDay.Weekday.Sat ); 383 Console.WriteLine( cday.isWeekday() ); 384 Console.WriteLine( cday.isWeekend() ); 385 } 386 } 387 \end{csharp} 388 \end{tabular} 389 \lstMakeShortInline@ 390 \caption{\Csharp: Free Routine Versus Class Enumeration} 391 \label{CsharpFreeVersusClass} 392 \end{figure} 367 393 368 394 369 395 \section{Golang} 370 371 \lstnewenvironment{Go}[1][]{% necessary 372 \lstset{ 373 language=Go, 374 escapechar=\$, % LaTeX escape in code 375 moredelim=**[is][\color{red}]{@}{@}, % red highlighting @...@ 376 }% lstset 377 \lstset{#1}% necessary 378 }{} 379 380 The Golang enumeration is similar to classic Pascal \lstinline[language=pascal]{const}, binding a name to a constant literal/expression. 396 \lstnewenvironment{Go}[1][]{\lstset{language=Go,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{} 397 398 Golang provides a mechanism similar to classic Pascal \lstinline[language=pascal]{const}, binding a name to a constant literal/expression (pseudo enumeration). 381 399 \begin{Go} 382 400 const ( R = 0; G; B ) $\C{// implicit: 0 0 0}$ … … 401 419 Auto-incrementing stops after an explicit initialization. 402 420 \begin{Go} 403 const ( Mon day = iota; Tuesday; Wednesday; // 0, 1, 2404 @Thu rsday = 10@; Friday; Saturday; Sunday) // 10, 10, 10, 10421 const ( Mon = iota; Tue; Wed; // 0, 1, 2 422 @Thu = 10@; Fri; Sat; Sun ) // 10, 10, 10, 10 405 423 \end{Go} 406 424 Auto-incrementing can be restarted with an expression containing \emph{one} \lstinline[language=Go]{iota}. 407 425 \begin{Go} 408 426 const ( V1 = iota; V2; @V3 = 7;@ V4 = @iota@; V5 ) // 0 1 7 3 4 409 const ( Mon day = iota; Tuesday; Wednesday; // 0, 1, 2410 @Thu rsday = 10;@ Friday = @iota - Wednesday + Thursday - 1@; Saturday; Sunday) // 10, 11, 12, 13427 const ( Mon = iota; Tue; Wed; // 0, 1, 2 428 @Thu = 10;@ Fri = @iota - Wed + Thu - 1@; Sat; Sun ) // 10, 11, 12, 13 411 429 \end{Go} 412 430 Note, \lstinline[language=Go]{iota} is advanced for an explicitly initialized enumerator, like the underscore @_@ identifier. 413 431 432 Basic switch and looping are possible. 433 \begin{cquote} 434 \lstDeleteShortInline@ 435 \setlength{\tabcolsep}{15pt} 436 \begin{tabular}{@{}ll@{}} 437 \begin{Go} 438 day := Mon; 439 switch day { 440 case Mon, Tue, Wed, Thu, Fri: 441 fmt.Println( "weekday" ); 442 case Sat, Sun: 443 fmt.Println( "weekend" ); 444 } 445 \end{Go} 446 & 447 \begin{Go} 448 449 for i := Mon; i <= Sun; i += 1 { 450 fmt.Println( i ) 451 } 452 453 454 455 \end{Go} 456 \end{tabular} 457 \lstMakeShortInline@ 458 \end{cquote} 459 The loop prints the values from 0 to 13 because there is no actual enumeration. 460 414 461 415 462 \section{Java} 416 417 \lstnewenvironment{Java}[1][]{% necessary 418 \lstset{ 419 language=Java, 420 escapechar=\$, % LaTeX escape in code 421 moredelim=**[is][\color{red}]{`}{`}, % red highlighting @...@ 422 }% lstset 423 \lstset{#1}% necessary 424 }{} 425 426 Here's a quick and simple example of an enum that defines the status of a pizza order; the order status can be ORDERED, READY or DELIVERED: 463 \lstnewenvironment{Java}[1][]{\lstset{language=Java,escapechar=\$,moredelim=**[is][\color{red}]{!}{!},}\lstset{#1}}{} 464 465 Every enumeration in Java is an enumeration class. 466 For a basic enumeration 427 467 \begin{Java} 428 public enum PizzaStatus { 429 ORDERED, 430 READY, 431 DELIVERED; 432 } 468 enum Weekday { Mon, Tue, Wed, Thu, Fri, Sat, Sun }; 469 Weekday day = Weekday.Sat; 433 470 \end{Java} 434 Additionally, enums come with many useful methods that we would otherwise need to write if we were using traditional public static final constants. 435 436 \paragraph{Custom Enum Methods} 437 438 Now that we have a basic understanding of what enums are and how we can use them, we'll take our previous example to the next level by defining some extra API methods on the enum: 471 the scoped enumerators are an ordered list of @final@ methods of type integer, ordered left to right starting at 0, increasing by 1. 472 The value of an enumeration instance is restricted to the enumeration's enumerators. 473 There is an implicit integer variable in the enumeration used to store the value of an enumeration instance. 474 The position (ordinal) and label are accessible, and the value is the same as the position. 439 475 \begin{Java} 440 public class Pizza { 441 private PizzaStatus status; 442 public enum PizzaStatus { 443 ORDERED, 444 READY, 445 DELIVERED; 446 } 447 public boolean isDeliverable() { 448 if (getStatus() == PizzaStatus.READY) { 449 return true; 450 } 451 return false; 452 } 453 // Methods that set and get the status variable. 454 } 476 System.out.println( !day.ordinal()! + " " + !day! ); // 5 Sat 455 477 \end{Java} 456 457 \paragraph{Comparing Enum Types Using "==" Operator} 458 459 Since enum types ensure that only one instance of the constants exist in the JVM, we can safely use the "==" operator to compare two variables, like we did in the above example. 460 Furthermore, the "==" operator provides compile-time and run-time safety. 461 462 First, we'll look at run-time safety in the following snippet, where we'll use the "==" operator to compare statuses. 463 Either value can be null and we won't get a NullPointerException. Conversely, if we use the equals method, we will get a NullPointerException: 478 There are no implicit conversions to/from an enumerator and its underlying type. 479 480 To explicitly assign enumerator values, the enumeration must specify an explicit type in the enumeration class. 464 481 \begin{Java} 465 if(testPz.getStatus().equals(Pizza.PizzaStatus.DELIVERED)); 466 if(testPz.getStatus() == Pizza.PizzaStatus.DELIVERED); 482 enum Weekday { 483 Mon( -4 ), Tue( -3 ), Wed( -2 ), Thu( -1 ), Fri( 0 ), Sat( 1 ), Sun( 2 ); // must appear first 484 private int day; $\C{// underlying enumeration type}$ 485 private Weekday( int d ) { day = d; } $\C{// used to initialize enumerators and instances}$ 486 }; 487 Weekday day = Weekday.Sat; $\C{// implicit constructor call}$ 467 488 \end{Java} 468 As for compile-time safety, let's look at an example where we'll determine that an enum of a different type is equal by comparing it using the equals method. 469 This is because the values of the enum and the getStatus method coincidentally are the same; 470 however, logically the comparison should be false. We avoid this issue by using the "==" operator. 471 472 The compiler will flag the comparison as an incompatibility error: 489 The position, value, and label are accessible. 473 490 \begin{Java} 474 if(testPz.getStatus().equals(TestColor.GREEN)); 475 if(testPz.getStatus() == TestColor.GREEN); 491 System.out.println( !day.ordinal()! + " " + !day.day! + " " + !day! ); // 5 1 Sat 476 492 \end{Java} 477 478 \paragraph{Using Enum Types in Switch Statements} 479 480 We can use enum types in switch statements also: 493 The constructor is private so only initialization or assignment can be used to set an enumeration, which ensures only corresponding enumerator values are allowed. 494 495 Like \Csharp, \VRef[Figure]{f:JavaFreeVersusClass} shows the same example for an enumeration with free routines for manipulation, and embedding the enumeration and operations into an enumeration class. 496 497 \begin{figure} 498 \centering 499 \lstDeleteShortInline@ 500 \begin{tabular}{@{}l|l@{}} 501 \multicolumn{1}{@{}c|}{non-object oriented} & \multicolumn{1}{c@{}}{object oriented} \\ 502 \hline 481 503 \begin{Java} 482 public int getDeliveryTimeInDays() { 483 switch (status) { 484 case ORDERED: return 5; 485 case READY: return 2; 486 case DELIVERED: return 0; 487 } 488 return 0; 504 public class test { 505 506 enum Weekday { 507 Mon, Tue, Wed, Thu, Fri, Sat, Sun }; 508 509 static boolean isWeekday( Weekday wd ) { 510 return Weekday.Mon.ordinal() <= wd.ordinal() 511 && wd.ordinal() <= Weekday.Fri.ordinal(); 512 } 513 static boolean isWeekend( Weekday wd ) { 514 return Weekday.Sat.ordinal() <= wd.ordinal() 515 && wd.ordinal() <= Weekday.Sun.ordinal(); 516 } 517 518 519 public static void main( String[] args ) { 520 Weekday day = Weekday.Sat; 521 System.out.println( isWeekday( day ) ); 522 System.out.println( isWeekend( day ) ); 523 } 489 524 } 490 525 \end{Java} 491 492 \paragraph{Fields, Methods and Constructors in Enums} 493 494 We can define constructors, methods, and fields inside enum types, which makes them very powerful. 495 496 Next, let's extend the example above by implementing the transition from one stage of a pizza order to another. 497 We'll see how we can get rid of the if and switch statements used before: 526 & 498 527 \begin{Java} 499 public class Pizza { 500 private PizzaStatus status; 501 public enum PizzaStatus { 502 ORDERED (5){ 503 @Override 504 public boolean isOrdered() { 505 return true; 506 } 507 }, 508 READY (2){ 509 @Override 510 public boolean isReady() { 511 return true; 512 } 513 }, 514 DELIVERED (0){ 515 @Override 516 public boolean isDelivered() { 517 return true; 518 } 519 }; 520 521 private int timeToDelivery; 522 public boolean isOrdered() {return false;} 523 public boolean isReady() {return false;} 524 public boolean isDelivered(){return false;} 525 public int getTimeToDelivery() { 526 return timeToDelivery; 527 } 528 PizzaStatus (int timeToDelivery) { 529 this.timeToDelivery = timeToDelivery; 530 } 531 } 532 public boolean isDeliverable() { 533 return this.status.isReady(); 534 } 535 public void printTimeToDeliver() { 536 System.out.println("Time to delivery is " + 537 this.getStatus().getTimeToDelivery()); 538 } 539 // Methods that set and get the status variable. 528 public class test { 529 public !enum! WeekDay { 530 Mon(-4), Tue(-3), Wed(-2), Thu(-1), 531 Fri(0), Sat(1), Sun(2); 532 private int day; 533 public boolean isWeekday() { 534 return day <= 0; 535 536 } 537 public boolean isWeekend() { 538 return day > 0; 539 540 } 541 private WeekDay( int d ) { day = d; } 542 } 543 public static void main( String[] args ) { 544 WeekDay day = WeekDay.Sat; 545 System.out.println( day.isWeekday() ); 546 System.out.println( day.isWeekend() ); 547 } 540 548 } 541 549 \end{Java} 542 The test snippet below demonstrates how this works: 550 \end{tabular} 551 \lstMakeShortInline@ 552 \caption{Java: Free Routine Versus Class Enumeration} 553 \label{f:JavaFreeVersusClass} 554 \end{figure} 555 556 An enumeration can appear in a @switch@ statement, but no ranges. 543 557 \begin{Java} 544 @Test 545 public void givenPizaOrder_whenReady_thenDeliverable() { 546 Pizza testPz = new Pizza(); 547 testPz.setStatus(Pizza.PizzaStatus.READY); 548 assertTrue(testPz.isDeliverable()); 558 switch ( day ) { 559 case Mon: case Tue: case Wed: case Thu: case Fri: 560 System.out.println( "weekday" ); 561 break; 562 case Sat: case Sun: 563 System.out.println( "weekend" ); 564 break; 549 565 } 550 566 \end{Java} 551 552 \paragraph{EnumSet and EnumMap} 553 554 \paragraph{EnumSet} 555 556 The EnumSet is a specialized Set implementation that's meant to be used with Enum types. 557 558 Compared to a HashSet, it's a very efficient and compact representation of a particular Set of Enum constants, owing to the internal Bit Vector Representation that's used. 559 It also provides a type-safe alternative to traditional int-based "bit flags," allowing us to write concise code that's more readable and maintainable. 560 561 The EnumSet is an abstract class that has two implementations, RegularEnumSet and JumboEnumSet, one of which is chosen depending on the number of constants in the enum at the time of instantiation. 562 563 Therefore, it's a good idea to use this set whenever we want to work with a collection of enum constants in most scenarios (like subsetting, adding, removing, and bulk operations like containsAll and removeAll), and use Enum.values() if we just want to iterate over all possible constants. 564 565 In the code snippet below, we can see how to use EnumSet to create a subset of constants: 567 Looping over an enumeration is done using method @values@, which returns the array of enumerator values. 566 568 \begin{Java} 567 public class Pizza { 568 private static EnumSet<PizzaStatus> undeliveredPizzaStatuses = 569 EnumSet.of(PizzaStatus.ORDERED, PizzaStatus.READY); 570 private PizzaStatus status; 571 public enum PizzaStatus { 572 ... 573 } 574 public boolean isDeliverable() { 575 return this.status.isReady(); 576 } 577 public void printTimeToDeliver() { 578 System.out.println("Time to delivery is " + 579 this.getStatus().getTimeToDelivery() + " days"); 580 } 581 public static List<Pizza> getAllUndeliveredPizzas(List<Pizza> input) { 582 return input.stream().filter( 583 (s) -> undeliveredPizzaStatuses.contains(s.getStatus())) 584 .collect(Collectors.toList()); 585 } 586 public void deliver() { 587 if (isDeliverable()) { 588 PizzaDeliverySystemConfiguration.getInstance().getDeliveryStrategy() 589 .deliver(this); 590 this.setStatus(PizzaStatus.DELIVERED); 591 } 592 } 593 // Methods that set and get the status variable. 569 for ( Weekday iday : Weekday.values() ) { 570 System.out.println( iday.ordinal() + " " + iday + " " ); 594 571 } 595 572 \end{Java} 596 573 597 Executing the following test demonstrates the power of the EnumSet implementation of the Set interface: 598 \begin{Java} 599 @Test 600 public void givenPizaOrders_whenRetrievingUnDeliveredPzs_thenCorrectlyRetrieved() { 601 List<Pizza> pzList = new ArrayList<>(); 602 Pizza pz1 = new Pizza(); 603 pz1.setStatus(Pizza.PizzaStatus.DELIVERED); 604 605 Pizza pz2 = new Pizza(); 606 pz2.setStatus(Pizza.PizzaStatus.ORDERED); 607 608 Pizza pz3 = new Pizza(); 609 pz3.setStatus(Pizza.PizzaStatus.ORDERED); 610 611 Pizza pz4 = new Pizza(); 612 pz4.setStatus(Pizza.PizzaStatus.READY); 613 614 pzList.add(pz1); 615 pzList.add(pz2); 616 pzList.add(pz3); 617 pzList.add(pz4); 618 619 List<Pizza> undeliveredPzs = Pizza.getAllUndeliveredPizzas(pzList); 620 assertTrue(undeliveredPzs.size() == 3); 621 } 622 \end{Java} 623 624 \paragraph{EnumMap} 625 626 EnumMap is a specialized Map implementation meant to be used with enum constants as keys. 627 Compared to its counterpart HashMap, it's an efficient and compact implementation that's internally represented as an array: 628 \begin{Java} 629 EnumMap<Pizza.PizzaStatus, Pizza> map; 630 \end{Java} 631 Let's look at an example of how we can use it in practice: 632 \begin{Java} 633 public static EnumMap<PizzaStatus, List<Pizza>> 634 groupPizzaByStatus(List<Pizza> pizzaList) { 635 EnumMap<PizzaStatus, List<Pizza>> pzByStatus = 636 new EnumMap<PizzaStatus, List<Pizza>>(PizzaStatus.class); 637 638 for (Pizza pz : pizzaList) { 639 PizzaStatus status = pz.getStatus(); 640 if (pzByStatus.containsKey(status)) { 641 pzByStatus.get(status).add(pz); 642 } else { 643 List<Pizza> newPzList = new ArrayList<Pizza>(); 644 newPzList.add(pz); 645 pzByStatus.put(status, newPzList); 646 } 647 } 648 return pzByStatus; 649 } 650 \end{Java} 651 Executing the following test demonstrates the power of the EnumMap implementation of the Map interface: 652 \begin{Java} 653 @Test 654 public void givenPizaOrders_whenGroupByStatusCalled_thenCorrectlyGrouped() { 655 List<Pizza> pzList = new ArrayList<>(); 656 Pizza pz1 = new Pizza(); 657 pz1.setStatus(Pizza.PizzaStatus.DELIVERED); 658 659 Pizza pz2 = new Pizza(); 660 pz2.setStatus(Pizza.PizzaStatus.ORDERED); 661 662 Pizza pz3 = new Pizza(); 663 pz3.setStatus(Pizza.PizzaStatus.ORDERED); 664 665 Pizza pz4 = new Pizza(); 666 pz4.setStatus(Pizza.PizzaStatus.READY); 667 668 pzList.add(pz1); 669 pzList.add(pz2); 670 pzList.add(pz3); 671 pzList.add(pz4); 672 673 EnumMap<Pizza.PizzaStatus,List<Pizza>> map = Pizza.groupPizzaByStatus(pzList); 674 assertTrue(map.get(Pizza.PizzaStatus.DELIVERED).size() == 1); 675 assertTrue(map.get(Pizza.PizzaStatus.ORDERED).size() == 2); 676 assertTrue(map.get(Pizza.PizzaStatus.READY).size() == 1); 677 } 678 \end{Java} 679 680 \paragraph{Singleton Pattern} 681 682 Normally, implementing a class using the Singleton pattern is quite non-trivial. 683 Enums provide a quick and easy way of implementing singletons. 684 685 In addition, since the enum class implements the Serializable interface under the hood, the class is guaranteed to be a singleton by the JVM. 686 This is unlike the conventional implementation, where we have to ensure that no new instances are created during deserialization. 687 688 In the code snippet below, we see how we can implement a singleton pattern: 689 \begin{Java} 690 public enum PizzaDeliverySystemConfiguration { 691 INSTANCE; 692 PizzaDeliverySystemConfiguration() { 693 // Initialization configuration which involves 694 // overriding defaults like delivery strategy 695 } 696 697 private PizzaDeliveryStrategy deliveryStrategy = PizzaDeliveryStrategy.NORMAL; 698 699 public static PizzaDeliverySystemConfiguration getInstance() { 700 return INSTANCE; 701 } 702 703 public PizzaDeliveryStrategy getDeliveryStrategy() { 704 return deliveryStrategy; 705 } 706 } 707 \end{Java} 708 709 \paragraph{Strategy Pattern} 710 711 Conventionally, the Strategy pattern is written by having an interface that is implemented by different classes. 712 713 Adding a new strategy means adding a new implementation class. 714 With enums, we can achieve this with less effort, and adding a new implementation means simply defining another instance with some implementation. 715 716 The code snippet below shows how to implement the Strategy pattern: 717 \begin{Java} 718 public enum PizzaDeliveryStrategy { 719 EXPRESS { 720 @Override 721 public void deliver(Pizza pz) { 722 System.out.println("Pizza will be delivered in express mode"); 723 } 724 }, 725 NORMAL { 726 @Override 727 public void deliver(Pizza pz) { 728 System.out.println("Pizza will be delivered in normal mode"); 729 } 730 }; 731 732 public abstract void deliver(Pizza pz); 733 } 734 \end{Java} 735 Then we add the following method to the Pizza class: 736 \begin{Java} 737 public void deliver() { 738 if (isDeliverable()) { 739 PizzaDeliverySystemConfiguration.getInstance().getDeliveryStrategy() 740 .deliver(this); 741 this.setStatus(PizzaStatus.DELIVERED); 742 } 743 } 744 745 @Test 746 public void givenPizaOrder_whenDelivered_thenPizzaGetsDeliveredAndStatusChanges() { 747 Pizza pz = new Pizza(); 748 pz.setStatus(Pizza.PizzaStatus.READY); 749 pz.deliver(); 750 assertTrue(pz.getStatus() == Pizza.PizzaStatus.DELIVERED); 751 } 752 \end{Java} 753 754 8. Java 8 and Enums 755 756 We can rewrite the Pizza class in Java 8, and see how the methods getAllUndeliveredPizzas() and groupPizzaByStatus() become so concise with the use of lambdas and the Stream APIs: 757 \begin{Java} 758 public static List<Pizza> getAllUndeliveredPizzas(List<Pizza> input) { 759 return input.stream().filter( 760 (s) -> !deliveredPizzaStatuses.contains(s.getStatus())) 761 .collect(Collectors.toList()); 762 } 763 764 public static EnumMap<PizzaStatus, List<Pizza>> 765 groupPizzaByStatus(List<Pizza> pzList) { 766 EnumMap<PizzaStatus, List<Pizza>> map = pzList.stream().collect( 767 Collectors.groupingBy(Pizza::getStatus, 768 () -> new EnumMap<>(PizzaStatus.class), Collectors.toList())); 769 return map; 770 } 771 \end{Java} 574 As well, Java provides an @EnumSet@ where the underlying type is an efficient set of bits, one per enumeration \see{\Csharp \lstinline{Flags}, \VRef{s:Csharp}}, providing (logical) operations on groups of enumerators. 575 There is also a specialized version of @HashMap@ with enumerator keys, which has performance benefits. 576 577 Enumeration inheritence is disallowed because an enumeration is @final@. 578 772 579 773 580 … … 778 585 779 586 \section{Swift} 780 781 \lstnewenvironment{swift}[1][]{% necessary 782 \lstset{ 783 language=Swift, 784 escapechar=\$, % LaTeX escape in code 785 moredelim=**[is][\color{red}]{@}{@}, % red highlighting @...@ 786 }% lstset 787 \lstset{#1}% necessary 788 }{} 587 \lstnewenvironment{swift}[1][]{\lstset{language=Swift,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{} 789 588 790 589 Model custom types that define a list of possible values.
Note: See TracChangeset
for help on using the changeset viewer.