###次のスクリプトファイルをコンパイルして実行する
####( クラス間の継承関係 )
HighLoyalityCustomerクラス --> NormalCustomerクラス --> Customerクラス --> Personクラス
####( 継承クラスのコンストラクタに付けた「上限境界」制約)
- CustomerContainerクラスのコンストラクタは、Customerクラスそれ自体か、Customerクラスのサブクラスのみ受け入れる。
class CustomerContainer[C <: Customer](c: C) {
- GoodCustomerContainerクラスのコンストラクタは、HighLoyalityCustomerクラスそれ自体か、HighLoyalityCustomerクラスのサブクラスのみ受け入れる。
>```Scala:
>class GoodCustomerContainer[H <: HighLoyalityCustomer](h: H) {
>```
```Scala:bounded_class_test.scala
object BoundedClassTest {
def main(args: Array[String]){
val customerContainer = new CustomerContainer[NormalCustomer](new NormalCustomer("Johnny", 15000))
val goodCustomerContainer = new GoodCustomerContainer[HighLoyalityCustomer](new HighLoyalityCustomer("Ben", 7200000, 235))
println(customerContainer.customer_name)
println(goodCustomerContainer.customer_name)
}
abstract class Person() {
def get_name: String
}
class Customer(val cust_name: String) extends Person() {
override def get_name: String = cust_name
}
class NormalCustomer(cust_name: String, val total_sales_price: Int) extends Customer(cust_name) {
def get_sales_volume: Int = total_sales_price
}
class HighLoyalityCustomer(cust_name: String, total_sales_price: Int, val total_purchased_num: Int) extends NormalCustomer(cust_name: String, total_sales_price: Int) {
def get_sales_count: Int = total_purchased_num
}
class CustomerContainer[C <: Customer](c: C) {
def customer_name: String = c.get_name
}
class GoodCustomerContainer[H <: HighLoyalityCustomer](h: H) {
def customer_name: String = h.get_name
}
}
###コンパイル実行(scalacコマンド)
- 警告メッセージWarningは出ますが、コンパイルに成功しました。
- スクリプトファイル内に記述したインスタンス生成のコードは、最初に見たすべての「上限境界」制約を満たしているので、コンパイルエラーを起こしませんでした。
Terminal
electron@diynoMacBook-Pro scala_test % scalac bounded_class_test.scala
warning: 1 deprecation (since 2.13.0); re-run with -deprecation for details
1 warning
electron@diynoMacBook-Pro scala_test %
- 実行ファイル(BoundedClassTest .class)以下、各種ファイルが生成されている
Terminal
electron@diynoMacBook-Pro scala_test % ls | grep BoundedClassTest
BoundedClassTest$.class
BoundedClassTest$Animal.class
BoundedClassTest$Cat.class
BoundedClassTest$Customer.class
BoundedClassTest$CustomerContainer.class
BoundedClassTest$Dog.class
BoundedClassTest$GoodCustomerContainer.class
BoundedClassTest$HighLoyalityCustomer.class
BoundedClassTest$Lion.class
BoundedClassTest$NormalCustomer.class
BoundedClassTest$Person.class
BoundedClassTest$Pet.class
BoundedClassTest$PetContainer.class
BoundedClassTest.class
electron@diynoMacBook-Pro scala_test %
###scalaコマンドでクラスファイルを実行
Terminal
electron@diynoMacBook-Pro scala_test % scala BoundedClassTest
Johnny
Ben
electron@diynoMacBook-Pro scala_test %
###REPLに読み込むスクリプトファイルを作成する
bounded_class_test2.scala
abstract class Person() {
def get_name: String
}
class Customer(val cust_name: String) extends Person() {
override def get_name: String = cust_name
}
class NormalCustomer(cust_name: String, val total_sales_price: Int) extends Customer(cust_name) {
def get_sales_volume: Int = total_sales_price
}
class HighLoyalityCustomer(cust_name: String, total_sales_price: Int, val total_purchased_num: Int) extends NormalCustomer(cust_name: String, total_sales_price: Int) {
def get_sales_count: Int = total_purchased_num
}
class CustomerContainer[C <: Customer](c: C) {
def customer_name: String = c.get_name
}
class GoodCustomerContainer[H <: HighLoyalityCustomer](h: H) {
def customer_name: String = h.get_name
}
}
- REPLにロードして実行する。
- REPL環境内で、最初に見たすべての「上限境界」制約を満たすインスタンス生成と、制約を満たさないインスタンス生成(の試み)を実行してみます。
Terminal
electron@diynoMacBook-Pro scala_test % scala
Welcome to Scala 2.13.6 (OpenJDK 64-Bit Server VM, Java 17.0.1).
Type in expressions for evaluation. Or try :help.
scala> :load bounded_class_test2.scala
val args: Array[String] = Array()
Loading bounded_class_test2.scala...
class Person
class Customer
class NormalCustomer
class HighLoyalityCustomer
class CustomerContainer
class GoodCustomerContainer
}
^
bounded_class_test2.scala:1: error: eof expected but '}' found.
scala>
- customerContainerクラスのコンストラクタは、NormalCustomerクラスのインスタンス(new NormalCustomer("Johnny", 15000))を初期化変数として受け入れる。
Terminal
scala> val customerContainer = new CustomerContainer[NormalCustomer](new NormalCustomer("Johnny", 15000))
val customerContainer: CustomerContainer[NormalCustomer] = CustomerContainer@3cc2e3e
scala> println(customerContainer.customer_name)
Johnny
- goodCustomerContainerクラスのコンストラクタは、HighLoyalityCustomerクラスのインスタンス(*new HighLoyalityCustomer("Ben", 7200000, 235))を初期化変数として受け入れる。
Terminal
scala> val goodCustomerContainer = new GoodCustomerContainer[HighLoyalityCustomer](new HighLoyalityCustomer("Ben", 7200000, 235))
val goodCustomerContainer: GoodCustomerContainer[HighLoyalityCustomer] = GoodCustomerContainer@7272914b
scala> println(goodCustomerContainer.customer_name)
Ben
- goodCustomerContainerクラスのコンストラクタは、NormalCustomerクラスのインスタンス(new NormalCustomer("Johnny", 15000))を初期化変数として受け入れることができない。
- goodCustomerContainerクラスは、上限境界であるHighLoyalityCustomerそれ自体か、HighLoyalityCustomerのサブクラスしか、初期化変数として受け入れない。
Terminal
scala> val goodCustomerContainer = new GoodCustomerContainer[NormalCustomer](new NormalCustomer("Johnny", 15000))
^
error: type arguments [NormalCustomer] do not conform to class GoodCustomerContainer's type parameter bounds [H <: HighLoyalityCustomer]
^
error: type arguments [NormalCustomer] do not conform to class GoodCustomerContainer's type parameter bounds [H <: HighLoyalityCustomer]
- Personクラスは抽象クラスなので、インスタンスオブジェクトを生成できない(*new Person()*は実行不能)
- 抽象クラスを継承したサブクラスからは、インスタンスを生成できる(そのサブクラスが抽象クラスでない場合)
Terminal
scala> val goodCustomerContainer = new GoodCustomerContainer[Person](new Person())
^
error: class Person is abstract; cannot be instantiated
- CustomerContainerクラスのコンストラクタは、HighLoyalityCustomerクラスのインスタンス(new HighLoyalityCustomer("Ben", 7200000, 235))を初期化変数として受け入れる。
- CustomerContainerクラスのコンストラクタは、上限境界であるCustomerクラスそれ自体か、Customerクラスのサブクラスのインスタンスを受け入れることができる。
- HighLoyalityCustomerクラスは、この「Customerクラスのサブクラス」という制約条件を満たしている。
Terminal
scala> val customerContainer = new CustomerContainer[HighLoyalityCustomer](new HighLoyalityCustomer("Ben", 7200000, 235))
val customerContainer: CustomerContainer[HighLoyalityCustomer] = CustomerContainer@23adbd6b
scala> println(customerContainer.customer_name)
Ben
scala>
ここで、以下が成立します。
- HighLoyalityCustomerクラスは、NormalCustomerクラスのサブクラスである。
- そのため、__もしも、CustomerContainerクラスの下限境界がNormalCustomerであったとしたら、「NormalCustomerのサブクラスである」 HighLoyalityCustomerクラスは受け入れられなかった。
- HighLoyalityCustomerクラスは、「NormalCustomerクラスそれ自体か、NormalCustomerクラスのスーパークラスであること」という制約条件を満たさないため。
REPLを抜ける。
Terminal
scala> :q
electron@diynoMacBook-Pro scala_test %
( 参考にしたウェブページ )