.. index:: 
	single: Object Oriented Programming; Introduction

=================================
Object Oriented Programming (OOP)
=================================

In this chapter we are going to learn how to use the Object-Oriented programming paradigm
inside the Ring programming language.

We will learn about

* Classes and Objects
* Access Objects Using Braces
* Composition
* Setter and Getter
* Private Attributes and Methods
* Operator Overloading
* Inheritance
* Dynamic Attributes
* Packages
* Printing Objects
* Find() and List of Objects
* Sort() and List of Objects
* Using Self.Attribute and Self.Method()
* Using This.Attribute and This.Method()


.. index:: 
	pair: Object Oriented Programming; Classes and Objects


Classes and Objects
===================

We can define new classes using the next syntax

Syntax:

.. code-block:: ring

	Class <Class Name> [From|<|: <Parent Class Name>]
		[Attributes]
		[Methods]
		[Private
 		  [Attributes]
		  [Methods]
                ]

And we can create objects using the next syntax

Syntax:

.. code-block:: ring

	New <Object Name> [ (init method parameters) ] |
			  [ { access object data and methods } ]   ---> Object

Example:

.. code-block:: ring

	New point { x=10  y=20  z=30  print() }
	Class Point x y z func print see x + nl + y + nl + z + nl 

.. note:: We can use { } to access object data and methods.

.. tip:: we can declare the class attributes directly after the class name.

Output:

.. code-block:: ring

	10
	20
	30

We can rewrite the same program in another style

.. code-block:: ring

	New point 			# create new object using the point class
	{ 				# access the new object attributes and methods
		x = 10 			# set the x attribute to 10
		y = 20 			# set the y attribute to 20
		z = 30 			# set the z attribute to 30
		print() 		# call the print method
	}				# end of object access 


	Class Point 			# define the Point class
		x y z 			# the class contains three attributes x, y & z
		func print 		# define the print method
			see x + nl +    # print the x attribute
			    y + nl +    # print the y attribute
			    z + nl 	# print the z attribute



Also we can write the same program in another way

.. code-block:: ring

	P1 = New Point
	P1.x = 10
	P1.y = 20
	P1.z = 30
	P1.Print()
	Class Point x y z func print see x + nl + y + nl + z + nl 	

.. note:: we can use the dot operator after the object name to access object members.

Also we can write the same program in another way

.. code-block:: ring

	new point { print() } 	
	Class Point
		x = 10  y = 20  z = 30
		func print see x + nl + y + nl + z + nl

.. note:: we can set the default values for the class attributes when we declare them.

Also we can write the same program in another way

.. code-block:: ring

	new point(10,20,30)
	Class Point
		x y z 
		func init p1,p2,p3 x=p1 y=p2 z=p3 print()
		func print see x + nl + y + nl + z + nl

.. note:: we can call the init method directly using () when we create new objects 

Also we can write the same program in another way

.. code-block:: ring

	new point( [ :x = 10 , :y = 20 , :z = 30 ] )
	Class Point x y z
	      func init aPara x = aPara[:x] y = aPara[:y] z = aPara[:z] print()
     	      func print see x + nl + y + nl + z + nl

.. tip:: using Hash for passing method parameters enable us to create optional 
         parameters and change the order of parameters when adding them to the Hash.

.. index:: 
	pair: Object Oriented Programming; Access Objects Using Braces

Access Objects Using Braces
===========================

We can access the object at any time using braces { } 

Inside the braces we can use the object attributes and methods directly

This can be done when we create the object using the New keyword or at any time using the next syntax

.. code-block:: ring

	ObjectName { access object data and methods }

Example:

.. code-block:: ring

	See "Creating the Object" + nl
	o1 = new Point
	See "Using the Object" + nl
	o1 {
		x=5 	
		y=15
		z=25	
		print()
	}
	Class Point x y z func print see x + nl + y + nl + z 

We can use braces to access objects when we call functions or methods

Example:

.. code-block:: ring

	o1 = new Point

	print( o1 { x=10 y=20 z=30 } )
	
	func print object
		see object.x + nl + 
		    object.y + nl + 
		    object.z 

	Class Point x y z

We can mix between using braces and the dot operator to access the object in the same expression.


Example:

.. code-block:: ring

	o1 = new Point

	O1 { x=10 y=20 z=30 }.print()
	
	Class Point x y z
		func print see x + nl + y + nl + z

.. index:: 
	pair: Object Oriented Programming; Composition

Composition
===========

The object may contains other objects as attributes.

Using braces to access objects can be nested.

Example:

.. code-block:: ring

	R1 = New Rectangle 
	{

		Name = "Rectangle 1"

		P1 
		{
			X = 10
			Y = 20
		}

		P2 
		{
			X = 200
			Y = 300
		}	

	        Color = "Blue"

	}
	
	see "Name : " + R1.Name + nl +
	    "Color: " + R1.Color + nl +
	    "P1   : (" + R1.P1.X + "," + R1.P1.Y + ")" + nl + 
	    "P2   : (" + R1.P2.X + "," + R1.P2.Y + ")"  

	Class Rectangle
		name  color
		p1 = new Point
		p2 = new Point

	Class Point x y 

Output:

.. code-block:: ring

	Name : Rectangle 1
	Color: Blue
	P1   : (10,20)
	P2   : (200,300)

.. index:: 
	pair: Object Oriented Programming; Setter and Getter

Setter and Getter
=================

We can define methods to be used when we set and get object attributes.

Syntax:

.. code-block:: ring

	Class ClassName

		AttributeName
		...

		Func SetAttributeName
			...

		Func GetAttributeName
			...

Example:

.. code-block:: ring

	o1 = new person

	o1.name = "Mahmoud"  see o1.name + nl

	o1 { name = "Ahmed"  see name }

	Class Person

		name family = "Fayed"

		func setname value
			see "Message from SetName() Function!" + nl
			name = value + " " + family

		func getname
			see "Message from GetName() Function!" + nl
			return "Mr. " + name

Output:

.. code-block:: ring

	Message from SetName() Function!
	Message from GetName() Function!
	Mr. Mahmoud Fayed
	Message from SetName() Function!
	Message from GetName() Function!
	Mr. Ahmed Fayed

.. index:: 
	pair: Object Oriented Programming; Private Attributes and Methods

Private Attributes and Methods
==============================		

We can define private attributes and methods after the keyword private inside the class body

Example:

.. code-block:: ring

	o1 = new person {
		name = "Test"
		age = 20
		print()
		o1.printsalary()
	}

	try
		see o1.salary
	catch
		see cCatchError + nl
	done

	try
		o1.increasesalary(1000)
	catch
		see cCatchError + nl
	done

	Class Person

		name age 

		func print
			see "Name   : " + name + nl + 
			    "Age    : " + age + nl 

		func printsalary
		  	see "Salary : " + salary + nl 

		private

		salary = 15000

		func increasesalary x
			salary += x

Output:

.. code-block:: ring

	Name   : Test
	Age    : 20
	Salary : 15000
	Error (R27) : Using private attribute from outside the class : salary
	Error (R26) : Calling private method from outside the class : increasesalary

.. index:: 
	pair: Object Oriented Programming; Operator Overloading

Operator Overloading
====================

We can add the operator method to our class to enable using operators with the class objects.

Syntax:

.. code-block:: ring

	Class ClassName

		...

		Func operator cOperator,Para

			...

The function operator takes two paramters, the first represent the operator
and the second represent the second parameter after the operator.

Example:

.. code-block:: ring

	o1 = new point { x = 10 y = 10 print("P1    : ") }
	o2 = new point { x = 20 y = 40 print("P2    : ") }

	o3 = o1 + o2
	o3.print("P1+P2 : ")

	class point x y

		func operator cOperator,Para
			result = new point	
			switch cOperator
			on "+"
				result.x = x + Para.x
				result.y = y + Para.y
			on "-"
				result.x = x - Para.x
				result.y = y - Para.y
			off
			return result

		func print cPoint
			see cPoint + "X : " + x + " Y : " + y + nl

Output:

.. code-block:: ring

	P1    : X : 10 Y : 10
	P2    : X : 20 Y : 40
	P1+P2 : X : 30 Y : 50


The next example from the List class in the stdlib.ring

.. code-block:: ring

	Func operator cOperator,Para
		result = new list
		switch cOperator
			on "+"
				if isobject(para)
					for t in Para.vValue
						vValue + t
					next
				but islist(para)
					for t in Para
						vValue + t
					next
				ok
			on "len"
				return len( vValue )
			on "[]"
				return &vValue[para]
		off
		return result

The "len" operator is used with (for in) control structure.

The "[]" operator is used when we try to access the list items, In this case we use the & operator
to return the item values like strings an numbers by reference, so we can update it when we access the
items.

Another Example

.. code-block:: ring

	func main 

	See "----1"+nl
	    a1 = new BigNumber( "123" )
	    a2 = new BigNumber( "456" )
	    a3 = new BigNumber( "789" )
	See nl+"----2"+nl  
		a1.print()
		a2.print()
		a3.print()
	See nl+"----3"+nl      
	    a2 = a1 + "45"  
	See nl+"----4"+nl  
	    a2.print()      
	See nl+"----5"+nl  
	    a3 = a1 + a2    
	See nl+"----6"+nl  
	    a3.print()      
	See nl+"----7"+nl

	###==================================
	Func FuncAdd( num1, num2)
	   Sum = 0 + num1 + num2    ### Para.aData isNumber
	   Sum = "" +Sum            ### Para.adata isString
	return Sum                  ### return to Class
	###===================================

	class BigNumber 

	    ### Variables
	    aData = "468"

	    ### Functions INIT default values
	    func init aPara 
		? "INIT aPara: " ? aPara
		if isString(aPara)
		    aData = aPara 
		else 
		    aData = "" + aPara
		ok

	    ### Other Functions
	    func operator cOperator, Para
		    whatType = Type(Para)
		    ? nl+"WhatType-PARA: "+ whatType ? Para 
		    ? nl+"Operator: " ? cOperator  ? nl+"PARA: " ? Para ? "    ______" ? nl
				    if whatType = "STRING"
				       dataInfo = Para
				       ? "dataInfo String: " ? dataInfo
				    but whatType = "NUMBER"
				       datinfo  = "" + Para
				       ? "dataInfo Number: " ? dataInfo
				    else whatType = "OBJECT"
				       dataInfo = "" + para.aData  
				       ? "dataInfo OBJECT: " ? dataInfo
				    ok
				  ? "dataInfo USING: " ? dataInfo  
		    ### Para.aData does NOT exist on first pass ( Object with member)
		    ### Result isObject when assigned "self"
		    result = self   
		    switch cOperator
			on "+"
			     answer = FuncAdd( aData, dataInfo )
			     ? nl+"AnswerString - FunAdd aData, dataInfo: " ? answer  
			     ### result = self, is Object, populate Object with aData member
			     result.aData = answer
			off
		    ### Result = Self is Object
		    return result   

	    func print 
		? nl+"ClassPrint aData: " ? aData 	

.. index:: 
	pair: Object Oriented Programming; Inheritance

Inheritance
===========

We can create class from another class in the class definition using the keyword from.

Syntax:

.. code-block:: ring

	Class <Class Name> [From <Parent Class Name>]

We can call a method in the parent class from the child class using the super object.

Syntax:

.. code-block:: ring

	func methodname
		...
		super.methodname()
		...

Example:

.. code-block:: ring

	Func main
		e1 = new Employee {
			Name = "test"
			age = 20
			job = "programmer"
			salary = 20000000
			print()
		}
	

	Class Human 
		Name Age
		func print
			see "Name : " + name + nl + "Age  : " + age + nl

	Class Employee from Human
		Job Salary
		func print
			super.print()
			see "Job  : " + job + nl + "Salary : " + salary + nl

Output:

.. code-block:: ring

	Name : test
	Age  : 20
	Job  : programmer
	Salary : 20000000

.. index:: 
	pair: Object Oriented Programming; Dynamic Attributes

Dynamic Attributes
==================

We can write instructions after the class name to be executed when we create new objects

Example:

.. code-block:: ring

	o1 = new dynamicClass
	see o1.var5 + nl	# output 5

	Class DynamicClass
		for x = 1 to 10
			cStr = "var" + x + " = " + x
			eval(cStr)
		next

.. tip:: in the previous example var1, var2, ..., var10 will be defined as attributes.

.. tip:: The problem with the previous example is that x and cStr will be defined as attributes too!

.. note:: we can write class definitions inside a string then 
          using eval() we can execute the string to define the classes

.. index:: 
	pair: Object Oriented Programming; Packages

Packages
========

We can create a package (a group of classes under a common name) using the next syntax

.. code-block:: ring

	package PackageName
		Class Class1
			...
		Class Class2
			...
		Class Class3
			...
		...

Example

.. code-block:: ring

	o1 = new System.output.console
	o1.print("Hello World")
	
	Package System.Output
		Class Console
			Func Print cText
				see cText + nl

.. note:: we can use the dot operator as part of the package name

Instead of typing the long name PackageName.ClassName we can use the import command

When we import a package, we can use any class inside this package directly.

Example

.. code-block:: ring

	import system.output
	o1 = new console {
		print("Hello World")
	}
	Package System.Output
		Class Console
			Func Print cText
				see cText + nl

.. index:: 
	pair: Object Oriented Programming; Printing Objects

Printing Objects
================

We can print the object state (attributes and values) using the see command.

Example:

.. code-block:: ring

	see new point { x=10 y=20 z=30 }
	class point x y z

Output:

.. code-block:: ring

	x: 10.000000
	y: 20.000000
	z: 30.000000

.. index:: 
	pair: Object Oriented Programming; Find() and List of Objects

Find() and List of Objects
==========================

We can use the find() function to search inside a list of objects.

Syntax:

.. code-block:: ring

	Find(List,ItemValue,nColumn,cAttribute) ---> Item Index

Example:

.. code-block:: ring

	myList1 = [new Company {position=3 name="Mahmoud" symbol="MHD"},
  		   new Company {position=2 name="Bert" symbol="BRT"},
		   new Company {position=1 name="Ring" symbol="RNG"}
		  ]

	see find(mylist1,"Bert",1,"name") + nl
	see find(mylist1,"Ring",1,"name") + nl
	see find(mylist1,"Mahmoud",1,"name") + nl
	see find(mylist1,"RNG",1,"symbol") + nl
	see find(mylist1,"MHD",1,"symbol") + nl
	see find(mylist1,"BRT",1,"symbol") + nl
	see find(mylist1,3,1,"position") + nl
	see find(mylist1,1,1,"position") + nl
	see "Other" + nl
	see find(mylist1,"test",1,"name") + nl
	see find(mylist1,"test",0,"name") + nl
	see find(mylist1,"test",5,"name") + nl

	class company position name symbol

Output:

.. code-block:: ring

	2
	3
	1
	3
	1
	2
	1
	3
	Other
	0
	0
	0

.. index:: 
	pair: Object Oriented Programming; Sort() and List of Objects

Sort() and List of Objects
==========================

We can sort a list of objects based on an object attribute using the Sort() function.

Syntax:

.. code-block:: ring

	Sort(List,nColumn,cAttribute) ---> Sorted List based on Object Attribute

Example:

.. code-block:: ring

	myList1 = [
			new Company {position=3 name="Mahmoud" symbol="MHD"},
			new Company {position=2 name="Bert" symbol="BRT"},
			new Company {position=8 name="Charlie" symbol="CHR"},
			new Company {position=6 name="Easy" symbol="FEAS"},
			new Company {position=7 name="Fox" symbol="EFOX"},
			new Company {position=5 name="Dog" symbol="GDOG"},
			new Company {position=4 name="George" symbol="DGRG"},
			new Company {position=1 name="Ring" symbol="RNG"}
		  ]

	see sort(mylist1,1,"name")
	see copy("*",70) + nl
	see sort(mylist1,1,"symbol")
	see copy("*",70) + nl
	see sort(mylist1,1,"position")

	class company position name symbol

Output:

.. code-block:: ring


	position: 2.000000
	name: Bert
	symbol: BRT
	position: 8.000000
	name: Charlie
	symbol: CHR
	position: 5.000000
	name: Dog
	symbol: GDOG
	position: 6.000000
	name: Easy
	symbol: FEAS
	position: 7.000000
	name: Fox
	symbol: EFOX
	position: 4.000000
	name: George
	symbol: DGRG
	position: 3.000000
	name: Mahmoud
	symbol: MHD
	position: 1.000000
	name: Ring
	symbol: RNG
	**********************************************************************
	position: 2.000000
	name: Bert
	symbol: BRT
	position: 8.000000
	name: Charlie
	symbol: CHR
	position: 4.000000
	name: George
	symbol: DGRG
	position: 7.000000
	name: Fox
	symbol: EFOX
	position: 6.000000
	name: Easy
	symbol: FEAS
	position: 5.000000
	name: Dog
	symbol: GDOG
	position: 3.000000
	name: Mahmoud
	symbol: MHD
	position: 1.000000
	name: Ring
	symbol: RNG
	**********************************************************************
	position: 1.000000
	name: Ring
	symbol: RNG
	position: 2.000000
	name: Bert
	symbol: BRT
	position: 3.000000
	name: Mahmoud
	symbol: MHD
	position: 4.000000
	name: George
	symbol: DGRG
	position: 5.000000
	name: Dog
	symbol: GDOG
	position: 6.000000
	name: Easy
	symbol: FEAS
	position: 7.000000
	name: Fox
	symbol: EFOX
	position: 8.000000
	name: Charlie
	symbol: CHR

.. index:: 
	pair: Object Oriented Programming; Using Self.Attribute

Using Self.Attribute and Self.Method()
======================================

Inside the class region (After the class name and before any method) and the class methods we can
use self.attribute and self.method()

.. code-block:: ring

	Class Point
		self.x = 10
		self.y = 20
		self.z = 30
		func print
			see self.x + nl + self.y + nl + self.z + nl

.. note:: using self.attribute in the class region to define the class attribute protect the class attributes from conflict with global variables.

.. tip:: if you typed the class attributes with self.attribute and there are a global variable with the same name it will be used and the attribute will not be defined.

Check the "Scope Rules" chapter to know about the conflict between the global variable name and the attribute name

Whay this may happens?

Because 

* Because in the class region we can access global variables.
* Before defining any variable, Ring try to find the variable and use it if it's found.

.. note:: Try to avoid the global variables, use the main function and start their names with $ 

.. tip:: In large programs protect your classes and define their members using self.attribute

.. index:: 
	pair: Object Oriented Programming; Using This.Attribute and This.Method()

Using This.Attribute and This.Method()
======================================

Inside class methods we have access to the object scope directly. we don't need to use Self.attribute
or Self.method to read/write attribute and call methods.

But we can use braces {} while we are inside methods to access another object, In this case the current
object scope will be changed while we are inside the brace.

How we can get access to our class attributes and methods while we are inside braces?

This can be done using This.Attribute and This.Method()

Example:

.. code-block:: ring

	new point  

	class point 
		x=10 y=20 z=30
		print()
		func print
			new UI {
				display(this.x,this.y,this.z)
			}

	Class UI
		func display x,y,z
			see x + nl + y + nl + z + nl

.. index:: 
	pair: Object Oriented Programming; Using This in the class region as Self

Using This in the class region as Self
======================================

The class region is the region that comes after the class name and before any method.

We can use This in the class region as Self.

Example:

.. code-block:: ring

	func main

		o1 = new program {
			test()
		}

		? o1

	class program 

		this.name = "My Application"
		this.version = "1.0"
		? name ? version	

		func test
			? "Name    = " + name 
			? "Version = " + version

Output

.. code-block:: none

	My Application
	1.0
	Name    = My Application
	Version = 1.0
	name: My Application
	version: 1.0

.. note:: When we use braces to change the current active object, Using This we can still point to the class.

.. tip:: The difference between This and Self is that Self point to the current active object that we can change using braces.

Remember that in most cases we don't need to use This or Self in the class region

We can write


.. code-block:: ring

	class program name version

Or 

.. code-block:: ring

	class program name="My Application" version="1.0"

.. note:: We use This or Self in the class region just to avoid conflict with global variables that are defined with the same name.


.. index:: 
	pair: Object Oriented Programming; Default value for object attributes

Default value for object attributes
===================================

The default value for object attributes is NULL

In Ring, the NULL value is just an empty string or a string that contains "NULL"

We can check for NULL values using the isNULL() function

Example:

.. code-block:: ring

	oProgram = new Program
	? oProgram.name
	? oProgram.version
	? isNULL(oProgram.name)
	? isNULL(oProgram.version)
	oProgram { name="My Application" version="1.0" }
	? isNULL(oProgram.name)
	? isNULL(oProgram.version)
	? oProgram

	class program
		name 
		version

Output:

.. code-block:: none

	NULL
	NULL
	1
	1
	0
	0
	name: My Application
	version: 1.0
