LoginSignup
32
24

More than 5 years have passed since last update.

Structural Subtyping とは - いげ太のブログ

structural subtyping (構造的部分型)とは、強い型付けによる恩恵は魅力的やな、でも型は定義しても継承関係までは定義したくない、制限による堅さに利はあるけど柔軟性を失いすぎるのもちょっとな、インターフェースばっかりいくつも定義するのもアホらしいし、その時々で適当なインターフェース割り振るようにしたらステキやん、というシグネチャ至上主義だ。

構造的部分型の比較 - まぁ、そんなもんでしょう

  • OCamlは全て型推論してくれる代わりに部分型への変換は明示的。部分型変換ができるバリアントがある。
  • haXeは全て型推論してくれて、かつ部分型への変換も暗黙的にできるけど、場合によってはコンパイルがとまらない
  • Scalaは型推論は(完璧には)してくれないけど、部分型への変換は暗黙的

Scalaの構造的部分型

// クラスAとBには継承関係は無い
class A {
  def zzz() = println("aaa")
}

class B {
  def zzz() = println("bbb")
}
scala> var z : { def zzz() } = _
z: AnyRef{def zzz(): Unit} = null

scala> z = new A
z: AnyRef{def zzz(): Unit} = A@61064425

scala> z.zzz()
<console>:9: warning: reflective access of structural type member method zzz should be enabled
by making the implicit value scala.language.reflectiveCalls visible.
This can be achieved by adding the import clause 'import scala.language.reflectiveCalls'
or by setting the compiler option -language:reflectiveCalls.
See the Scala docs for value scala.language.reflectiveCalls for a discussion
why the feature should be explicitly enabled.
              z.zzz()
                ^
aaa

上の警告は

$ scala -language:reflectiveCalls

で除ける。明示的に機能をオンにしないといけないのは、
リフレクションを使っていいよっていう許可を与えるため。

scala> class A { def zzz() = print("aaa") }
defined class A

scala> class B { def zzz() = print("bbb") }
defined class B

scala> val list = List[{ def zzz() }](new A, new B)
list: List[Object{def zzz(): Unit}] = List(A@f1da57d, B@194fad1)

scala> for(z <- list) z.zzz()
aaabbb
scala> def callzzz(x:X) = x.zzz()
<console>:7: error: not found: type X
       def callzzz(x:X) = x.zzz()
                     ^

scala> def callzzz(x:{def zzz()}) = x.zzz()
callzzz: (x: AnyRef{def zzz(): Unit})Unit

scala> callzzz(new A)
aaa
scala> callzzz(new B)
bbb

Xの部分を型推論させることはできないのかな?

HaXe

構造体(匿名オブジェクト)
http://haxe.org/manual/struct?version=17720

class Person { // Personクラスはname関数を持っている
  public function new() { }
  public function name() { return "osiire"; }
  public function age() { return 20; }
}
class Test {
  public static function main() {
    print(new Person());
  }
  public static function print( n ) { // name関数があればいい
   trace(n.name());
  }
}

結果

osiire

Personクラスがnameメソッドを持っていないとコンパイルエラー

class Person {
  public function new() { }
  public function age() { return 20; }
}
Build failure
Test.hx:10: characters 10-22 : Person should be { name : Void -> String }
Test.hx:10: characters 10-22 : Person has no field name
Test.hx:10: characters 10-22 : For function argument 'n'

OCaml

TypeScript

32
24
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
24