オーバーライドの仕組みがユルい【Objective-Cの良い所 その1】


Objective-Cのオブジェクト指向は複雑なルールが少なく、比較的自由に扱えます。堅苦しい規約も無く、プログラマの自由に任せるというC言語らしいスタンスを感じますね。

その中でも特に気に入っているのが、関数の上書き機能(オーバーライド)の緩さです。 親クラスと同名の関数を宣言するだけで、オーバーライドが実現出来てしまいます。

@interface A : NSObject @end
@implementation A
-(void)foo { puts("a"); }
@end

@interface B : A @end
@implementation B
-(void)foo { puts("b"); }
@end

[A.new foo]; // "a"
[B.new foo]; // "b"

他の言語ではもっと複雑で面倒

Swiftの場合

Swiftの場合は親クラス側でpublicキーワード等のアクセス修飾子が必要になるケースがあり、またオーバーライド時もoverride指定子の明示が必須になります。

class A {
  func callFoo() { foo() }
  func foo()     { print("A.foo") }
}

class B : A {
  // error: overriding declaration requires an 'override' keyword
  // func foo() { print("b") }
  override func foo() { print("B.foo") } // override指定子が必須
}

B().callFoo() // "B.foo"

C++の場合

C++の場合はoverride指定子の省略が可能ですが、親クラス側でvirtual指定子の指定が必須となっています。

struct A {
   void callFoo() { foo(); }
   void callBar() { bar(); }
           void foo() { puts("A.foo"); }
   virtual void bar() { puts("A.bar"); }
};

struct B : A {
   void foo() { puts("B.foo"); }
   void bar() { puts("B.bar"); }
};

B().callFoo(); // "A.foo"
B().callBar(); // "B.bar"

ただし、SwiftやC++に見られるこれらの面倒な仕様は、保守性や安全性、統一性のためには必須の仕組みでもあるため、デメリットとは言えないでしょう。むしろObjective-Cが自由すぎるのです。

まとめ

私はこのObjective-Cの緩さがたまらなく好きです。Objective-Cのオブジェクト指向にはシンプルさとは何かを再認識させてくれる仕様が多く、使っていて面白い言語だと感じます。


Objective-C「この変態!!」
私「な、なんで?!!」

広告