duck-typing: class A: f() { .... } g() { .... } class X: m(value) { value.f() value.g() ... } ======= class Y: m2() { ... x = X() x.m(B()) class B: f() { .... } ------- interface I f() g() --- class A { m1() } class B : A { m2() } class C : A {} class D : B {} A / \ B C / D A a = new A(); A a = new B(); A a = new C(); A a = new D(); a.m1() XXX a.m2() if (a is B) { B b = (B) a; b.m2(); } A a = new D(); a is D -> true a is B -> true a is A -> true a is C -> false if (a is B b) { }