忘れたときに備えた記録

トップ 最新 追記
2005|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|11|12|
2009|01|02|03|04|05|06|10|12|
2010|06|07|08|12|
2011|07|09|
2012|09|11|
2013|02|03|09|
2015|10|11|
2016|01|08|11|
2017|02|08|10|
2018|11|

2005-11-02(Wednesday)

Mix-in

以前挙げたサンプルがおかしいので、改めて実験。

趣旨

モジュールの中でモジュール変数を定義したとき、これを共有する範囲はどこまでか?

ソース

#!/usr/bin/ruby
module M
   def setm(v)
      @@m = v
   end

   def getm
      @@m
   end
end

class C1
   include M
   def set
      setm('Module var')
   end
   def put
      puts('C1')
      puts @@m
   end
end

class C2
   include M
   def put
      puts('C2')
      puts @@m
   end
end

class C3
   include M
   @@m = 0
   def put
      @@m = 1
      setm('set by C3')
      puts('C3')
      puts @@m
      puts getm
   end
end

class C4
   @@m = 0
   include M
   def put
      @@m = 2
      setm('set by C4')
      puts('C4')
      puts @@m
      puts getm
   end
end

c1 = C1.new
c2 = C2.new
c3 = C3.new
c4 = C4.new
c1.set
c1.put
c2.put
c3.put
c4.put

解説

M
モジュール変数を操作するモジュール。getmでモジュール変数を返す
C1
モジュールをインクルードして値を設定する
C2
モジュールをインクルードして値を使用する
C3
モジュールをインクルードして、モジュール変数と同名のクラス変数を定義。
C4
C3と同様で、インクルードの前にモジュール変数と同名のクラス変数を定義。

結果

hiraku@shako:~/tmp$ ./test.rb
C1
Module var
C2
Module var
C3
1
set by C3
C4
2
set by C4
C1
set by C4

結論

モジュール変数と同じ名前のクラス変数を持たなければ、普通に共有される。

同名のクラス変数を持つときは、変数を直接操作すると、クラス変数が変化してモジュール変数は変わらない。モジュールが提供するモジュール変数の操作メソッドを使うとモジュール変数にもアクセスできる(モジュール変数のメソッドがクラス変数を変更はしない)。

Tags: Ruby

2005-11-11(Friday)

手続き・関数に配列を渡す

配列の定義の仕方によって挙動が換わることが分かったのでまとめ。

ソース

program Project1;

{$APPTYPE CONSOLE}

uses
	SysUtils;

type
	TIntArray = Array of Integer;

procedure ChangeIntArray(A: TIntArray);
var
	I: Integer;
begin
	for I:=Low(A) to High(A) do Inc(A[I]);
end;

procedure ChangeArrayOfInt(A: Array Of Integer);
var
	I: Integer;
begin
	for I:=Low(A) to High(A) do Inc(A[I]);
end;

var
	A: Array of Integer;
	IA: TIntArray;
	I: Integer;
begin
	SetLength(A, 10);
	SetLength(IA, 10);
	for I:=Low(A) to High(A) do A[I] := I;
	for I:=Low(IA) to High(IA) do IA[I] := I;

	ChangeIntArray(IA);
	ChangeArrayOfInt(A);

	Writeln('Array of Integer');
	for I:=Low(A) to High(A) do Writeln(I, ':', A[I]);
	Writeln('TIntArray');
	for I:=Low(IA) to High(IA) do Writeln(I, ':', IA[I]);
	Readln;
end.

結果

Array of Integer
0:0
1:1
2:2
3:3
4:4
5:5
6:6
7:7
8:8
9:9
TIntArray
0:1
1:2
2:3
3:4
4:5
5:6
6:7
7:8
8:9
9:10

まとめ

Array of Integer 型の変数として渡すとオープン配列パラメータとして、ヘルプにあるとおり配列のコピーが作られてそれが渡される(値渡し)。よって、手続き・関数の中で変更しても呼び出し元には影響しない。

一方、TIntArray = Array of Integer という型を定義してその変数として渡すと、今度はその配列そのものが渡される(変数渡し)。よって、手続き・関数の中で変更すると呼び出し元に影響してしまう

Tags: Delphi

2005-11-14(Monday)

コンストラクタをインスタンスの中で呼ぶ

パラメータを指定するコンストラクタとパラメータを指定しないコンストラクタを用意して、後者ではデフォルトの値を使って前者を呼び出す。

このとき、ちゃんと自分自身に対する手続きとして呼び出しているかどうかを確認した。

ソース

program Project1;

{$APPTYPE CONSOLE}

uses
	SysUtils;

type
	TTest = class
	private
		FI: Integer;
	public
		constructor Create;overload;
		constructor Create(I: Integer);overload;
		property I: Integer read FI;
	end;
{ TTest }

constructor TTest.Create(I: Integer);
begin
	FI := I;
end;

constructor TTest.Create;
var
	T1, T2: TTest;
begin
	T1 := Create(1);
	T2 := TTest.Create(2);
	Writeln('Self : ', Integer(Self));
	Writeln('T1   : ', Integer(T1));
	Writeln('T2   : ', Integer(T2));

	T2.Free;
end;

begin
	TTest.Create.Free;
	Readln;
end.

結果

Self : 13568376
T1   : 13568376
T2   : 13568388

コンストラクタの中で、クラス名なしでCreateを呼ぶとただの関数として扱われる。

一方、クラス名つきで呼び出すと新たなインスタンスを作り出す。

Tags: Delphi

With の中でのSelf

ソース

program Project1;

{$APPTYPE CONSOLE}

uses
	SysUtils;

type
	TTest1 = class
	public
		procedure Proc;
	end;
	TTest2 = class
		procedure Proc;
		procedure Test(O: TTest1);
	end;
{ TTest2 }

procedure TTest2.Proc;
begin
	Writeln('Test2');
end;

procedure TTest2.Test(O: TTest1);
begin
	with O do Proc;
	with O do Self.Proc;
end;

{ TTest1 }

procedure TTest1.Proc;
begin
	Writeln('Test1');
end;

var
	T1: TTest1;
	T2: TTest2;
begin
	{ TODO -oUser -cConsole Main : この下にコードを記述してください }
	T1 := TTest1.Create;
	T2 := TTest2.Create;
	try
		T2.Test(T1);
	finally
		T1.Free;
		T2.Free;
	end;

	Readln;
end.

結果

Test1
Test2

Withの中でSelfを使っても、Withで指定したオブジェクトを指すわけではない。

Tags: Delphi