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