読者です 読者をやめる 読者になる 読者になる

Objective-C vs Java とその周辺

ガベゴレ有効を前提に、ありがちなOOPっぽいコードを、Objective-Cで書いてみました。
以下のコードは、GNUstepを使ってコンパイルしています。
http://www.gnustep.org/
あ、GNUstepのチュートリアルのコード残骸がちらほら…。

#include <stdio.h>
#include <Foundation/Foundation.h>  

@protocol MessageHolder
- (NSString *) message;
- (void) setMessage: (NSString *) text;
@end

@interface MessageHolderImpl : NSObject <MessageHolder>
{
@private
    NSString * message;
}
+ (const char *) classStringValue;
@end

@implementation MessageHolderImpl
+ (const char *) classStringValue;
{
    return "This is the string value of the Test class";
}
- (NSString *) message
{
    return message;
}
- (void) setMessage: (NSString *) text
{
    message = text;
}
@end

@interface MessageHolderFactory : NSObject
+ (id <MessageHolder>) newInstance;
@end

@implementation MessageHolderFactory
+ (id <MessageHolder>) newInstance
{
    return [[MessageHolderImpl alloc] init];
}
@end

int main(void)
{
  printf("%s\n", [MessageHolderImpl classStringValue]);
  
  id<MessageHolder> test = [MessageHolderFactory newInstance];
  [test setMessage: @"hoge"];
  printf("%s\n", [[test message] cString]);
  
  return 0;
}

で、Javaで同じようなものを書いてみました。バリバリJava5以上です。printfのギャップを埋めるコードは飛ばして読んでください。C言語みたいに、引数にchar[]を入れると表示可能な文字が出る仕掛けです。

import java.util.List;
import java.util.LinkedList;

interface MessageHolder {
    public void setMessage(String text);
    public String getMessgae();
}

class MessageHolderImpl implements MessageHolder { //extends Object
    private String message = null;
    
    public static char[] classStringValue() {
        return "This is the string value of the Test class".toCharArray();
    }
    public void setMessage(String text) {
        message = text;
    }
    public String getMessgae() {
        return message;
    }
}

class MessageHolderFactory { // extends Object
    public static MessageHolder newInstance() {
        return new MessageHolderImpl();
    }
}

public class MessageHolderTest {
    public static void main(String[] args) {
        printf("%s\n", MessageHolderImpl.classStringValue());
        
        MessageHolder test = MessageHolderFactory.newInstance();
        test.setMessage("hoge");
        printf("%s\n", test.getMessgae().toCharArray());
    }
    
    //C-like printf which translates char[] to String before output.
    private static void printf(String fmt, Object... values) {
        List<Object> converted = new LinkedList<Object>();
        for(Object v : values){
            converted.add((v instanceof char[]) ? String.valueOf((char[])v) : v);
        }
        Object[] args = converted.toArray();
        System.out.printf(fmt, args);
    }
}

まともにコンストラクタ書いてないので、あまりいいコード例じゃないですが、どんな感じでしょう?C言語資産を使うために、かぎ括弧の多重人格構文を受け入れるかどうか、悩みどころですね。Appleさん、早くNeXT文化からGCJかD言語に切り替えてくれないかな。

以下、ついでにわれらがインタプリタたち。言語仕様がメソッド実装を強制しないので、ソースコードコメントで対処w

#interface restriction!!
# Class that has getMessage and setMessage would be assumed as one of MessageHolder.

class MessageHolderImpl(object):
    @staticmethod
    def classStringValue():
        return "This is the string value of the Test class"
    def getMessage(self):
        return self.message
    def setMessage(self, text):
        self.message = text

def newMessageHolder():
    return MessageHolderImpl()

print MessageHolderImpl.classStringValue()

test = newMessageHolder()
test.setMessage("hoge")
print test.getMessage()
#interface restriction!!
# Class that has getMessage and setMessage would be assumed as one of MessageHolder.

class MessageHolderImpl
    def MessageHolderImpl.classStringValue
        "This is the string value of the Test class"
    end
    def message
        @message
    end
    def message= text
        @message = text
    end
end

def newMessageHolder
    MessageHolderImpl.new
end

puts MessageHolderImpl.classStringValue

test = newMessageHolder
test.message = "hoge"
puts test.message

驚くべきことに、初回実行でエラーなし。まあ、根本的に使いどころが違うのでずるいのですが、もしメモリとCPUの余剰パワーがあるんなら、Objective-CJNIC言語資産を活かすより、実はSWIGのほうが強いんじゃ?

という意味で、これ↓の動機がよくわからないのです。
http://cappuccino.org/
変数宣言に型がある!?へんなの〜。ていうかJavaScriptで別の言語のインタプリタ!

たしかに面白い発想なんだけど、でも、ECMAな言語でOOP構文サポートしたけりゃ、ActionScript2、っていうかhaXeが、記述性の面でも性能の面でも、正解なんじゃないのかな、と思うのですが…(ECMA4とかAS3とかは違う)。かぎ括弧で、ネイティブJavaScriptな部分とそうじゃない部分を区切りやすくしてでも、インタプリタにこだわる理由ってなんなんだろう?
JavaScriptJavaScriptとして書いておかないと、いま流行の超高速JavaScript実行系が最適化してくれないと思うので、デモ以上のことすると、わりと早くに頭打ちになりそうな気がしてなりません。それ考えると、constructor.prototype...の汚いコードをライブラリに押し込んで隠しておき、関数リテラルを含んだJSONからオブジェクトツリーを構築できるビルダーなんかを公開しておいて、アプリケーションコードはJavaScriptという関数プログラム言語を活かす、っていうレガシーな方法が王道じゃないのかな?

CocoaとObjective-Cって、そんなにハマるもの?「Appleの方法は正しい、Appleがどのぐらい正しいかではなく、Appleだからすべて正しい」って思考回路が出来上がってないかな。