程式扎記: [Scala IA] The Basics : Ch3. OOP in Scala - Modifiers

標籤

2016年8月31日 星期三

[Scala IA] The Basics : Ch3. OOP in Scala - Modifiers

Modifiers (p86) 
You’ve already seen a few modifiers in action, but let’s look deeper into them. Along with standard modifiers like private and protected, Scala has more modifiers and new abilities. 

The private modifier can be used with any definition, which means it’s only accessible in an enclosed class, its companion object, or a companion class. In Scala, you can qualify a modifier with a class or a package name. In the following example, the private modifier is qualified by class and package name: 
  1. package outerpkg.innerpkg  
  2.   
  3. class Outer {  
  4.     class Inner {  
  5.         private[Outer] def f() = "This is f"  
  6.         private[innerpkg] def g() = "This is g"  
  7.         private[outerpkg] def h() = "This is h"  
  8.     }  
  9. }  
Here, access to the f method can appear anywhere within the Outer class, but not outside it. The method g is accessible anywhere within outerpkg.innerpkg. It’s like the package private in Java. You could use it to make your methods available for unit tests in the same package. Because the h method is qualified with outerpkg, it can appear anywhere within outerpkg and its subpackages. Scala also lets you qualify the private modifier with thisprivate[this]. In this case, it means object private. And object private is only accessible to the object in which it’s defined. When members are marked with private without a qualifier, they’re called class-private

The protected modifier is applicable to class member definitions. It’s accessible to the defining class and its subclasses. It’s also accessible to a companion object of the defining class and companion objects of all the subclasses. Like the private modifier, you can also qualify the protected modifier with class, package, and this. By default, when you don’t specify any modifier, everything is public. Scala doesn’t provide any modifier to mark members as public

Like Java, Scala also provides an override modifier, but the main difference is that in Scala the override modifier is mandatory when you override a concrete member definition from the parent class. The overridemodifier can be combined with an abstract modifier, and the combination is allowed only for members of traits. This modifier means that the member in question must be mixed with a class that provides the concrete implementation. An example will demonstrate this fact. The following creates a DogMood trait (dogs are moody, you know) with an abstract greet method and an AngryMood trait that overrides it: 
  1. trait DogMood{  
  2.     def greet  
  3. }  
  4.   
  5. trait AngryMood extends DogMood {  
  6.     override def greet = {  
  7.         println("bark")  
  8.         super.greet  
  9.     }  
  10. }  
The problem with this code is the super.greet line. You can’t invoke the super greet method because it’s abstract. But super calls are important if you want your trait to be stackable so that it can get mixed in with other traits. In cases like this, you can mark the method with abstract override, which means it should be mixed in with some class that has the concrete definition of the greet method. To make this code compile, you have to add abstract along withoverride, as in the following: 
  1. trait AngryMood extends DogMood {  
  2.     abstract override def greet = {  
  3.         println("bark")  
  4.         super.greet  
  5.     }  
  6. }  
So you can use above design as below: 
  1. trait DogMood{  
  2.     def greet  
  3. }  
  4.   
  5.   
  6. trait AngryMood extends DogMood {  
  7.     abstract override def greet = {  
  8.         printf("Bark ~~ ")  
  9.         super.greet  
  10.     }  
  11. }  
  12.   
  13. class ADog extends DogMood{  
  14.     override def greet = { println("Wow---") }  
  15. }  
  16.   
  17. class BDog extends ADog with AngryMood  
  18.   
  19.   
  20. val bdog = new BDog()  
  21. bdog.greet   // Bark ~~ Wow---  
Scala has introduced a new modifier called sealed, which applies only to class definitions. It’s a little different from the final modifier; classes marked final in Scala can’t be overridden by subclasses. But classes marked sealed can be overridden as long as the subclasses belong to the same source file. You used sealed in a previous section when you created QueryOption case classes: 
  1. sealed trait QueryOption  
This is a common pattern when you want to create a defined set of subclasses but don’t want others to subclass it. 

Supplement 
Scala's Stackable Trait Pattern

沒有留言:

張貼留言

網誌存檔