.. index:: 
	single: 宣言型プログラミング; はじめに

================================
入れ子構造の宣言型プログラミング
================================

オブジェクト指向による入れ子構造の宣言型プログラミング環境の構築方法を学びます。

* リストへオブジェクトを作成するには
* コンポジションと参照によりオブジェクトとリストを返すには
* オブジェクトのアクセス完了後にコードを実行するには
* オブジェクト指向による宣言型プログラミング

.. index:: 
	pair: 宣言型プログラミング; リストへオブジェクトを作成するには

リストへオブジェクトを作成するには
====================================

リストの定義時にリストへオブジェクトを作成できます。

Add() 関数、または + 演算子により、必要なときにオブジェクトをリストへ追加できます。

用例:

.. code-block:: ring

	alist = [new point, new point, new point]	# # オブジェクトが三つあるリストを作成します。

	alist + [1,2,3]					# 別の項目をリストへ追加します。

	see "Item 4 is a list contains 3 items" + nl
	see alist[4] 

	add(alist , new point)
	alist + new point

	alist[5] { x = 100 y = 200 z = 300 }
	alist[6] { x = 50 y = 150 z = 250 }

	see "Object inside item 5" + nl
	see alist[5]
	see "Object inside item 6" + nl
	see alist[6]

	class point x y z

実行結果:

.. code-block:: ring

	Item 4 is a list contains 3 items
	1
	2
	3
	Object inside item 5
	x: 100.000000
	y: 200.000000
	z: 300.000000
	Object inside item 6
	x: 50.000000
	y: 150.000000
	z: 250.000000

.. index:: 
	pair: 宣言型プログラミング; 参照によりオブジェクトを返すには

コンポジションと参照によりオブジェクトとリストを返すには
========================================================

コンポジションの使用とクラス属性のオブジェクトがある場合、オブジェクトの返値は参照で返します。

呼び出し元で代入演算子を使う場合は、オブジェクトのコピーを作成します。

呼び出し元で代入演算子を使わない場合は、参照で返されたオブジェクトへ直接アクセスできます。

また、属性がリスト (オブジェクトではありません) でも同じ処理が適用されます。

.. note:: オブジェクト、およびリストは同じ規則で処理します。
	関数へ渡すときは、参照渡しになります。
	関数から返すときは、参照で返されたオブジェクト属性を除き値返しになります。

用例:

.. code-block:: ring

	o1 = new Container
	myobj = o1.addobj()	# 別のコピーを代入で作成します。
	myobj.x = 100
	myobj.y = 200
	myobj.z = 300
	see o1.aobjs[1]		# コンテナにあるオブジェクトを表示します。
	see myobj		# コピーの表示

	Class Container
		aObjs = []
		func addobj
			aobjs + new point
			return aobjs[len(aobjs)]	# オブジェクトを参照で返します。

	Class point 
		x  = 10
		y  = 20
		z  = 30

実行結果:

.. code-block:: ring

	x: 10.000000
	y: 20.000000
	z: 30.000000
	x: 100.000000
	y: 200.000000
	z: 300.000000

用例②:

.. code-block:: ring

	func main
		o1 = new screen  {
			content[point()] { 
				x = 100 
				y = 200
				z = 300		
			}
			content[point()] { 
				x = 50 
				y = 150
				z = 250		
			}
		}
		see o1.content[1]
		see o1.content[2]

	Class Screen
		content = []
		func point
			content + new point
			return len(content)

	Class point 
		x  = 10
		y  = 20
		z  = 30

実行結果:

.. code-block:: ring

	x: 100.000000
	y: 200.000000
	z: 300.000000
	x: 50.000000
	y: 150.000000
	z: 250.000000

用例③:

.. code-block:: ring

	func main
		o1 = New Screen  {
			point() { 		# 参照でオブジェクトへアクセスします。
				x = 100 
				y = 200
				z = 300		
			}
			point() { 		# 参照でオブジェクトへアクセスします。
				x = 50 
				y = 150
				z = 250		
			}
		}
		see o1.content[1]		
		see o1.content[2]

	Class Screen
		content = []
		func point
			content + new point
			return content[len(content)]	# オブジェクトを参照で返します。

	Class point x=10 y=20 z=30

実行結果:

.. code-block:: ring

	x: 100.000000
	y: 200.000000
	z: 300.000000
	x: 50.000000
	y: 150.000000
	z: 250.000000


.. index:: 
	pair: 宣言型プログラミング; オブジェクトのアクセス完了後にコードを実行するには

オブジェクトのアクセス完了後にコードを実行するには
==================================================

オブジェクト属性とメソッドを使うには { } でオブジェクトへアクセスします。

オブジェクトに BraceEnd() メソッドがある場合は、オブジェクトのアクセス完了直前に実行します。

用例:

.. code-block:: ring

	New Point { See "How are you?" + nl }

	Class Point x y z
		func braceend
			see "I'm fine, Thank you!" + nl

実行結果:

.. code-block:: ring

	How are you?
	I'm fine, Thank you!


.. index:: 
	pair: 宣言型プログラミング; オブジェクト指向による宣言型プログラミング

オブジェクト指向による宣言型プログラミング
==========================================

この機能でオブジェクト指向による入れ子構造の宣言型プログラミング環境の構築と使用を可能にします。

* { } によるオブジェクト属性、およびメソッドへのアクセス
* BraceEnd() メソッド
* 参照によるオブジェクト返し
* Setter (セッター) / Getter (ゲッター) メソッド (オプション扱い)

用例:

.. code-block:: ring

	# 宣言型プログラミング (入れ子構造)

	Screen() 
	{

		point() 
		{ 			
			x = 100 
			y = 200
			z = 300		
		}

		point() 
		{ 			 
			x = 50 
			y = 150
			z = 250		
		}
	}

	# 関数とクラス

	Func screen return new screen

	Class Screen

		content = []

		func point
			content + new point
			return content[len(content)]	

		func braceend
			see "I have " + len(content) + " points!"

	Class point 

		x=10 y=20 z=30

		func braceend		
			see self	

実行結果:

.. code-block:: ring

	x: 100.000000
	y: 200.000000
	z: 300.000000
	x: 50.000000
	y: 150.000000
	z: 250.000000
	I have 2 points!

.. index:: 
	pair: 宣言型プログラミング; コード品質の向上

コード品質の向上
================

メソッドで仮引数を使わないときは、メソッド名末尾の () を省略できます。これにより、コード品質の向上になります。 
この機能はオブジェクトメソッドとオブジェクト属性との機能に違いがあるため Ring では使えません。
オブジェクト属性へ Getter メソッドを定義するとき、同様の効果をコードの構文で実現できます。
例えば point() メソッドの定義ではなく point 属性値の取得で実行される
getpoint() メソッドを point 属性として定義します。変数名は () を省略できるため、
point() ではなく point と記述します。
getpoint() メソッドはオブジェクトの作成、およびオブジェクトの参照を返します。

用例:

.. code-block:: ring

	new Container 
	{
		Point 
		{ 
			x=10 
			y=20 
			z=30 
		}
	}

	Class Container
		aObjs = []
		point
		func getpoint
			aObjs + new Point
			return aObjs[len(aObjs)]

	Class Point x y z
		func braceend
			see "3D Point" + nl + x + nl + y + nl + z + nl

実行結果:

.. code-block:: ring

	3D Point
	10
	20
	30

