PHP Trait – Define Trait – Traits Definition

PHP Trait - Define Trait - Traits Definition - Hindi

PHP Trait – PHP 5.4.x Version में Add किया गया ये एक Special Concept है जो Single Inheritance Based PHP Language में भी Code के Reuse करने की सुविधा प्रदान करता है। Traits की वजह से हम PHP के Single Inheritance की कुछ Limitations को Ignore कर सकते हैं।

Traits का प्रयोग करके हम ऐसे Free Methods Create कर सकते हैं, जिन्हें एक से ज्यादा Classes में बिना Redefine किए हुए ज्यों का त्यों Member Methods की तरह Use कर सकते हैं।

यानी सामान्यतः ज्यादातर Classes में कुछ ऐसे Methods होते हैं, जो लगभग एक जैसा काम ही करते हैं। उदाहरण के लिए set() Method सामान्यतः Class के Objects के Data को Set करने का काम करता है, जबकि get() Method Class के Object के Data को Return करने का काम करता है। इसी तरह से display() Method लगभग हर Class में Class के Object के Data को Display करने का ही काम करता है।

इस प्रकार के काम करने वाले Methods को हम Class के बाहर Traits में Define कर सकते हैं और अपनी जरूरत के अनुसार इन्हें किसी भी Class में बिना Redefine किए हुए Reuse कर सकते हैं।

सरल शब्दों में कहें तो ये Methods एक प्रकार से लगभग OOPS के Friend Functions की तरह होते हैं, जो होते तो Class से बाहर हैं, लेकिन Class के Private Data को Access करने की क्षमता रखते हैं।

Traits को भी ठीक उसी तरह से Create किया जाता है, जिस तरह से हम Class Create करते हैं। अन्तर केवल इतना है कि Traits में हम केवल Methods को ही Define करते हैं Data Members को नहीं क्योंकि Traits में Define किए गए Methods को Directly Call नहीं किया जा सकता तथा हम किसी Trait का Direct Instance Create नहीं कर सकते, क्योंकि ये Class नहीं होते बल्कि Class के एक हिस्से के रूप में Use किए जाते हैं और Objects हमेंशा किसी न किसी Class के ही Create होते हैं।

इन्हें हमेंशा किसी ना किसी Class में use Keyword का प्रयोग करके Embed किया जाता है और Embed होने के बाद इन Traits में Defined Methods को केवल Class के Members के लिए ही Use किया जाता है।

हम एक Trait में एक से ज्यादा Functions को एक Group के रूप में Define करते हैं और जब भी हमें उस Group के Function की जरूरत Method के रूप में अपनी Class में होती है, हम इन Traits को अपनी Class में Use कर लेते हैं व Methods की Functionalities को Class के Methods की तरह उपयोग में ले लेते हैं।

Traits का प्रयोग करके हम बिना Inheritance की प्रक्रिया को Use किए हुए Composition द्वारा Class को Extend करने की सुविधा प्राप्त करते हैं। किसी Trait का Create करने के लिए हमें trait Keyword का प्रयोग करना होता है। इस Concept को समझने के लिए हम निम्न उदाहरण Program देखते हैं:

<?php
	trait GeneralMethods{
		public function set($property, $value){
			$this->$property = $value;
		}
		
		public function get($property){
			return $this->$property;
		}
	}
	
	class Time{
		private $hour, $minutes, $seconds;
		use GeneralMethods;
	}
	
	class Box{
		private $height, $width, $length;
		use GeneralMethods;
	}
	
	$cpu = new Box;
	$cpu->set('height', 12);
	$cpu->set('width', 12);
	$cpu->set('length', 12);
	
	echo "CPU Box: \n";
	echo "Height: " . $cpu->get('height') ."\n";
	echo "Width: " . $cpu->get('width') ."\n";
	echo "Length: " . $cpu->get('length') ."\n";
	echo "Volume: " . $cpu->get('height') * $cpu->get('width') * $cpu->get('length');
	
	echo "\n\nTime: ";
	$hmt = new Time;
	$hmt->set('hour', 12);
	$hmt->set('minutes', 12);
	$hmt->set('seconds', 12);
	
	echo $hmt->get('hour') .":" . $hmt->get('minutes') .":" . $hmt->get('seconds') ;
?>  

//Output
   Height: 12
   Width: 12
   Length: 12
   Volume: 1728

   Time: 12:12:12

इस Program में हमने get()set() Methods को Class के अन्दर नहीं बल्कि trait के अन्दर Define किया है और use Statement का प्रयोग करके इन दोनों Functions को दो अलग Classes BoxTime Class के Methods की तरह Use किया है। हम देख सकते हैं कि हमने दोनों ही Classes में get() व set() Method को Define नहीं किया है, फिर भी हम get() व set() Methods को दोनों ही Classes में इस तरह से Use कर पा रहे हैं, जैसे कि इन दोनों Methods को Class के अन्दर ही Define किया गया है। Traits हमें यही सुविधा देते हैं।

यानी हम समान प्रकार के Methods को एक Group के रूप में Define कर सकते हैं और फिर उन Methods को एक Group के रूप में किसी भी Class में Reuse कर सकते हैं जो कि एक बहुत ही उपयोगी सुविधा है।

Precedence of Methods

चूंकि हम एक ही Class में एक से ज्यादा Trait को use Keyword द्वारा Embed कर सकते हैं साथ ही Trait में ऐसे Methods भी हो सकते हैं, जिनके नाम Class में Define किए गए किसी Method के नाम के Identical हों अथवा जब हम किसी Base Class को Inherit करते हैं, तब भी हम Derived Class में Base Class के Method को Override कर सकते हैं।

इस प्रकार की स्थिति में Trait के Methods Inherit होने वाले Methods को Override करते हैं। यानी होता ये है कि पहले Trait के Methods को Current Class के Method Override करते हैं और फिर Trait के Methods, Inherit होने वाले Base Class Methods को Override करते हैं। यानी Finally Trait के Methods ही सभी समान नाम के Methods को Override करते हैं। इस प्रक्रिया को हम निम्न उदाहरण द्वारा बेहतर तरीके से समझ सकते हैं:

<?php
	class Base {
	    public function sayHello() {
	        echo 'Hello ';
	    }
	}
	
	trait SayWorld {
	    public function sayHello() {
	        parent::sayHello();
	        echo 'World!';
	    }
	}
	
	class MyHelloWorld extends Base {
	    use SayWorld;
	}
	
	$object = new MyHelloWorld();
	$object->sayHello();
?>

इस Program में सबसे पहले MyHelloWorld Class का एक $object Create किया जाता है। Class का Object Create होते ही Class के Codes Memory में Space Reserve करते हैं, परिणामस्वरूप MyHelloWorld Class में SayWorld नाम का Trait Embed हो जाता है।

अब इस Object के लिए जब sayHello() Method को Invoke किया जाता है, तो ये Object Current Class में sayHello() Method को Search करता हैं चूंकि ये Method Trait के माध्यम से Current Class में Available है, इसलिए Trait का sayHello() Method Execute होता है।

Trait के sayHello() Method के Invoke होते ही parent::sayHello() Method Execute होता है जो Base Class के sayHello() Method को Call करता है। परिणामस्वरूप Base Class का sayHello() Method Hello Print करता है। फिर Control फिर से Trait के sayHello() Method में पहुंचता है और वहां पर “World!” शब्द को Print करता है। इस प्रकार से Final Output के रूप में हमें निम्नानुसार Output प्राप्त होता हैः

//Output
Hello World!

इस प्रकार से उपरोक्त Code में Base Class से Inherit होने वाले sayHello() Method को Trait से आने वाला sayHello() Method Override करता है। ठीक उसी तरह से जिस तरह से Derived Class में Define किया गया समान नाम का Method Base Class के Method को Override करता है।

तो Methods के Override होने का क्रम ये होता है कि Current Class में Define किया गया Method Trait में Define किए गए Method को Override करता है और Resultant Method Base Class के Method को Override करता है।

Method Overriding Precedence को थोडा और बेहतर तरीके से समझने के लिए हम एक और उदाहरण देखते हैं। ये उदाहरण निम्नानुसार हैः

<?php
	trait HelloWorld {
	    public function sayHello() {
	        echo 'Hello World!';
	    }
	}
	
	class TheWorldIsNotEnough {
	    use HelloWorld;
	    public function sayHello() {
	        echo 'Hello Universe!';
	    }
	}
	
	$object = new TheWorldIsNotEnough();
	$object->sayHello();
?>

//Output
   Hello Universe!

इस Program में हमने $object नाम का एक Object Create किया है और इस Object के लिए sayHello() नाम के Method को Call किया है। जैसे ही ये Method Call होता है, Class Memory में Space Reserve करता है और Trait के Code को Class में Import कर लेता है।

परिणामस्वरूप Current Class में sayHello() नाम के दो Methods हो जाते हैं। एक Trait का sayHello() व दूसरा Current Class TheWorldIsNotEnough का sayHello()

चूंकि जैसाकि हमने पहले भी कहा कि Current Class का Method Trait के Method को Override करता है, परिणामस्वरूप इस Program के Output में हमें “Hello Universe!” दिखाई दे रहा है, न कि “Hello World!” क्योंकि Current Class के sayHello() Method ने Trait के sayHello() Method को Override कर लिया है।

Multiple PHP Trait

जिस तरह से हम किसी एक Class में एक से ज्यादा Interfaces को Implement कर सकते हैं उसी तरह से हम किसी एक Class में एक से ज्यादा Traits को भी Use कर सकते हैं। इसे समझने के लिए हम हमारे पिछले Program को ही निम्नानुसार Modify कर सकते हैं:

<?php
	trait Set{
		public function set($property, $value){
			$this->$property = $value;
		}
	}
	
	trait Get{
		public function get($property){
			return $this->$property;
		}
	}
	
	class Time{
		private $hour, $minutes, $seconds;
		use Get;
		use Set;
	}
	
	echo "Time: ";
	$hmt = new Time;
	$hmt->set('hour', 12);
	$hmt->set('minutes', 12);
	$hmt->set('seconds', 12);
	
	echo $hmt->get('hour') .":" . $hmt->get('minutes') .":" . $hmt->get('seconds') ;
?>

इस Program में हमने Get व Set नाम के दो Traits Create किए हैं और Time नाम की Class में दोनों ही Traits को use Keyword द्वारा Import कर लिया है। यदि हम चाहें तो एक ही Use Statement द्वारा एक से ज्यादा Traits को किसी Class में Import कर सकते हैं। ऐसा करने के लिए हमें Comma Operator का प्रयोग करते हुए विभिन्न Traits को एक साथ Use Statement के साथ Specify करना होता है। जैसेः

<?php
	…
	…
	
	class Time{
		private $hour, $minutes, $seconds;
		use Get, Set;
	}
	
	…
	…
?>

Conflict Resolution

यदि दो Traits में एक समान नाम के Methods हों, तो PHP Fatal Error Generate करता है। इसलिए इस Conflict को हमें Manually Resolve करना जरूरी होता है। Naming Conflict को Resolve करने के लिए हम insteadof Operator को Use कर सकते हैं।

जब हम insteadof Operator को Use करते हैं तब PHP दोनों Traits में से किसी एक Trait के ही Method को Current Class में Include करता है। जबकि कई बार स्थिति ऐसी होती है, कि हमें दोनों ही Traits के Methods की जरूरत होती है।

इस स्थिति में हम PHP के as Operator का प्रयोग करके Trait के Method को एक दूसरे नाम के साथ Current Class में Include करना पडता है।

<?php
	trait AngleShape{
		public function input($height, $width){
			$this->height = $height;
			$this->width = $width;
		}
	}
	
	trait CircleShape{
		public function input($radius){
			$this->radius = $radius;
		}
	}
	
	trait GeneralMethod{
		public function get($property){
			return $this->$property;
		}
	}
	
	class Shape{
		private $height, $width, $radius;
		const PI = 3.1415;
		
		use AngleShape, CircleShape, GeneralMethod;
	}
	
	class Circle extends Shape{
		public function area(){
			return parent::PI * $this->get('radius') * $this->get('radius'); 
		}		
	}
	
	class Rectangle extends Shape{
		public function area(){
			return $this->get('height') * $this->get('width'); 
		}		
	}
?>

इस Program में हमने AngleShape, CircleShapeGeneralMethod नाम के तीन Traits Create किए हैं। फिर हमने Shape नाम की एक Class Create की है और इस Shape Class में AngleShape व CircleShape दोनों Traits को Import किया है, जबकि दोनों ही Traits में input() नाम का एक Method है, जो कि Collision कर रहा है। परिणामस्वरूप जब हम इस Script को Interpret करते हैं, तो हमें निम्नानुसार Error प्राप्त होता हैः

//Output:
Fatal error: Trait method input has not been applied, because there are collisions with other trait methods on Shape in C:\wamp\www\phpInHindi\001.php on line 26

इस Collision से बचने के लिए हम इस Program को निम्नानुसार insteadof Operator का प्रयोग करके Modify कर सकते हैं:

<?php
	trait AngleShape{
		public function input($height, $width){
			$this->height = $height;
			$this->width = $width;
		}
	}
	
	trait CircleShape{
		public function input($radius){
			$this->radius = $radius;
		}
	}
	
	trait GeneralMethod{
		public function get($property){
			return $this->$property;
		}
	}
	
	class Shape{
		private $height, $width, $radius;
		const PI = 3.1415;
		
		use GeneralMethod;
		use AngleShape, CircleShape{
			AngleShape::input insteadof CircleShape;
		}
	}
	
	class Circle extends Shape{
		public function area(){
			return parent::PI * $this->get('radius') * $this->get('radius'); 
		}		
	}
	
	class Rectangle extends Shape{
		public function area(){
			return $this->get('height') * $this->get('width'); 
		}		
	}
?>

अब यदि हम इस Program को Interpret करें, तो PHP कोई Error नहीं देता, लेकिन अब हमारी जरूरत ठीक से पूरी नहीं हो सकती। क्योंकि इस Program में हमने insteadof Operator का प्रयोग करके AngleShape के input() Method को तो Current Class में Available कर लिया है, जबकि CircleShape Class के input() Method को Reject कर दिया है। जबकि वास्तव में हमें Current Class में ही दोनों input() Methods की जरूरत है।

क्योंकि जब हम Rectangle Type के Shape के लिए Input Values Accept करते हैं, तब हमें input() Method में दो Parameters HeightWidth Accept करने होते हैं, जिसके लिए हमने AngleShape Trait में input() Method Define किया है, जबकि Circle Type के Shape के लिए Input Values Accept करते समय हमें केवल एक मान यानी Radius Accept करना होता है, जिसके लिए हमने CircleShape Trait में input() Method Define किया है।

यानी यदि हम उपरोक्त Program को ही उपयोग में लें, तो हम हमारे Program में केवल Angle Shapes जैसे कि Rectangle, SquareTriangle का ही Area Calculate कर सकते हैं, Circle या Ellipse जैसे Shapes का नहीं। क्योंकि हमने Shapes के लिए Input लेने वाले input() Method को निम्न Statement लिखकर Reject कर दिया हैः

		use AngleShape, CircleShape{
			AngleShape::input insteadof CircleShape;
		}

ये Statement Current PHP Script को कहता है कि Current Class में CircleShape के input() Method के बजाय AngleShape के input() Method को Use कर लिया जाए। जबकि वास्तव में हमें दोनों ही Traits के input() Methods की जरूरत है।

इसलिए हमें इस Statement को Modify करना होगा और insteadof Operator के स्थान पर as Operator को Use करते हुए CircleShape Trait के input() Method को किसी दूसरे नाम से Current Class में Import करना होगा, तभी हमारी जरूरत पूरी हो सकती है। इस जरूरत को हम अपने उपरोक्त Code को निम्नानुसार Modify करके पूरा कर सकते हैं:

		use AngleShape, CircleShape{
			AngleShape::input insteadof CircleShape;
			CircleShape::input as circleInput;
		}

अब इस Modified Code को अपने पिछले Program में Replace करने पर हम AngleShapeCircleShape दोनों ही प्रकार के Shapes को Create करने के लिए अलग-अलग संख्‍या में Input Parameters Accept कर सकते हैं व एक ही Shape Class द्वारा विभिन्न प्रकार के Shapes का Area Calculate कर सकते हैं।

<?php
	trait CircleShape{
		public function input($radius){
			$this->radius = $radius;
		}
	}
	
	trait AngleShape{
		public function input($height, $width){
			$this->height = $height;
			$this->width = $height;
		}
	}
	
	trait GeneralMethod{
		public function get($property){
			return $this->$property;
		}
	}
	
	class Shape{
		private $height, $width, $radius;
		const PI = 3.1415;
		
		use GeneralMethod, AngleShape, CircleShape{
			AngleShape::input insteadof CircleShape;
			CircleShape::input as inputCircle;
		}
	}
	
	class Circle extends Shape{
		public function area(){
			return parent::PI * $this->get('radius') * $this->get('radius'); 
		}		
	}
	
	class Rectangle extends Shape{
		public function area(){
			return $this->get('height') * $this->get('width'); 
		}		
	}
	
	$rect = new Rectangle;
	$rect->input(12, 2);
	Echo "Rectangle Area: " . $rect->area() . "\n";
	
	$cir = new Circle;
	$cir->inputCircle(10);
	Echo "Circle Area : " . $cir->area() . "\n";
?>  

//Output
   Rectangle Area: 144
   Circle Area : 314.15

अब उपरोक्त Program बिना किसी परेशानी के बिल्कुल Normal तरीके से Run होता है और हमें उपयुक्त Output देता है। इस Program की अन्तिम Lines में हम देख सकते हैं कि हमने $cir Object के लिए input() Method नहीं बल्कि inputCircle() Method को ब्ंसस किया है और ये नाम CircleShape Trait में Define किए गए input() Method का Alias ही है।

जब हम Traits को Use कर रहे होते हैं, तब मूल रूप से ध्यान रखने वाली बात यही होती है कि जब ये Codes Run होते हैं, तब हम जिस Class में Trait को use Keyword का प्रयोग करके Import करते हैं, उस Class में ये Codes ठीक इस तरह से Embed हो जाते हैं, जैसे कि इन्हें उस Class में ही लिखा गया हो।

यानी यदि हम उपरोक्त Program के Run होते समय की स्थिति को Normal Class की तरह Represent करें, तो हम उपरोक्त Program को निम्नानुसार भी लिख सकते हैं:

<?php
	class Shape{
		private $height, $width, $radius;
		const PI = 3.1415;
		
		public function inputCircle($radius){
			$this->radius = $radius;
		}

		public function input($height, $width){
			$this->height = $height;
			$this->width = $height;
		}
	
		public function get($property){
			return $this->$property;
		}	
	}
	
	class Circle extends Shape{
		public function area(){
			return parent::PI * $this->get('radius') * $this->get('radius'); 
		}		
	}
	
	class Rectangle extends Shape{
		public function area(){
			return $this->get('height') * $this->get('width'); 
		}		
	}
	
	$rect = new Rectangle;
	$rect->input(12, 2);
	Echo "Area: " . $rect->area() . "\n";
	
	$cir = new Circle;
	$cir->inputCircle(10);
	Echo "Circle Area : " . $cir->area() . "\n";
?>  

//Output
   Rectangle Area: 144
   Circle Area : 314.15

जैसाकि उपरोक्त Program के Output में भी हम देख सकते हैं कि हमें Exactly वही Output प्राप्त हो रहा है जो पिछले Program का प्राप्त हो रहा था। यानी पिछला Program वास्तव में Internally इसी Form में Convert होकर Run होता है। इसलिए जब भी कभी Trait का प्रयोग करें, उसके Expanded Form को ध्यान में रखें, तो गलतियां होने की संभावना कम रहती है।

Changing Method Visibility

as Operator का प्रयोग करके हम किसी Trait के Method की Visibility यानी Scope को भी Change कर सकते हैं। साथ ही हम as Operator का प्रयोग करके किसी Method का Alias भी Create कर सकते हैं, जैसाकि पिछले Program में किया था।

हमने हमारे पिछले Program में सभी Methods की Visibility को public रखा था। अब यदि हम चाहते हैं कि हम हमारे सभी Methods को Class में use Keyword का प्रयोग करके Embed करते समय उन्हें protected Scope के साथ Import करें, तो हम इस जरूरत को पूरा करने के लिए सभी Methods के Scope को निम्नानुसार Modify कर सकते हैं:

		use GeneralMethod, AngleShape, CircleShape{
			AngleShape::input insteadof CircleShape;
			CircleShape::input as inputCircle;
			
			input as protected;
			get as private myGetMethod;
		}

हालांकि यदि हम हमारे पिछले Program में ही इस Code को इस प्रकार से Modify कर दें, तो हमारे पिछले Program में Error Generate हो जाएगा, क्योंकि input()get() Method के Public होने की स्थिति में ही हम Shape Class के Private Data members को Access कर पा रहे हैं।

Traits in Trait

जिस तरह से हम किसी Class में किसी Trait को use Keyword का प्रयोग करके Use करते हैं, उसी तरह से हम किसी Trait में किसी दूसरे Trait को भी use Keyword का प्रयोग करके Import कर सकते हैं। उदाहरण के लिए यदि हम हमारे पिछले Program के सभी Traits को AllTraits नाम के Trait में Bind करना चाहें, तो हम हमारा नया Trait निम्नानुसार बना सकते हैं:

	trait CircleShape{
		public function input($radius){
			$this->radius = $radius;
		}
	}
	
	trait AngleShape{
		public function input($height, $width){
			$this->height = $height;
			$this->width = $height;
		}
	}
	
	trait GeneralMethod{
		public function get($property){
			return $this->$property;
		}
	}

	trait AllTraits{
		use GeneralMethod, AngleShape, CircleShape;
	}

अब यदि हम इस AllTraits Trait को अपने पिछले Program में use करना चाहें, तो हम हमारी Shape Class में इस Trait को निम्नानुसार Use कर सकते हैं:

	class Shape{
		private $height, $width, $radius;
		const PI = 3.1415;
		
		use AllTraits;
	}

यदि हम हमारे पिछले Program में इस Code को इसी तरह से लिख दें, तो हमें Collision Error ही मिलेगा, क्योंकि AllTraits में दो ऐसे Traits हैं, जिनमें input() नाम के दो Methods हैं। परिणामस्वरूप हमें हमारे AllTraits Trait को Specify करते समय निम्नानुसार लिखना होगाः

	trait AllTraits{
		use GeneralMethod, AngleShape, CircleShape{
			AngleShape::input insteadof CircleShape;
			CircleShape::input as inputCircle;
		}
	}

अब यदि हम हमारे पिछले Modified Program को देखें, तो यह Program निम्नानुसार दिखाई देना चाहिएः

<?php
	trait CircleShape{
		public function input($radius){
			$this->radius = $radius;
		}
	}
	
	trait AngleShape{
		public function input($height, $width){
			$this->height = $height;
			$this->width = $height;
		}
	}
	
	trait GeneralMethod{
		public function get($property){
			return $this->$property;
		}
	}
	
	trait AllTraits{
		use GeneralMethod, AngleShape, CircleShape{
			AngleShape::input insteadof CircleShape;
			CircleShape::input as inputCircle;
		}
	}
	
	class Shape{
		private $height, $width, $radius;
		const PI = 3.1415;
		
		use AllTraits;
	}
	
	class Circle extends Shape{
		public function area(){
			return parent::PI * $this->get('radius') * $this->get('radius'); 
		}		
	}
	
	class Rectangle extends Shape{
		public function area(){
			return $this->get('height') * $this->get('width'); 
		}		
	}
	
	$rect = new Rectangle;
	$rect->input(12, 2);
	Echo "Area: " . $rect->area() . "\n";
	
	$cir = new Circle;
	$cir->inputCircle(10);
	Echo "Circle Area : " . $cir->area() . "\n";
?>

Abstract Traits

हम हमारे किसी भी Trait में किसी भी method को Abstract Declare कर सकते हैं। जब हम किसी Method को Abstract Declare करते हैं किसी भी Abstract Class पर Apply होने वाले सारे Rules उस Abstract Function पर Apply हो जाते हैं।

परिणामस्वरूप हम जिस Class में इस Abstract Method वाले Trait को Use करते हैं, वह Class एक Abstract Class की तरह Behave करती है। इसलिए उस Class को एक Normal Class की तरह Behave करवाने के लिए हमें उस Class में Trait के Abstract Method को Implement करना जरूरी होता है। हम किसी Trait में निम्नानुसार Abstract Method Declare कर सकते हैं:

<?php
	trait GeneralMethods{
		public function set($property, $value){
			$this->$property = $value;
		}
	
		abstract public function get($property);
	}
	
	class Time{
		private $hour, $minutes, $seconds;
		use GeneralMethods;
		
		public function get($property){
			return $this->$property;
		}
	}
	
	echo "Time: ";
	$hmt = new Time;
	$hmt->set('hour', 12);
	$hmt->set('minutes', 12);
	$hmt->set('seconds', 12);
	
	echo $hmt->get('hour') .":" . $hmt->get('minutes') .":" . $hmt->get('seconds') ;
?>

इस Program में हमने GeneralMethods नाम के Trait में get() नाम के Method को Abstract Declare किया है। इसीलिए हमने Time Class में इस Method को Implement किया है।

यदि हम Time Class में इस Method को Implement नहीं करते, तो ये Time Class भी एक Abstract Class की तरह Behave करता, जिससे हम इस Class के भी Object Create नहीं कर पाते।

Static Trait Members

हम किसी Trait में Statement Members भी Define कर सकते हैं और जब हम किसी Trait में किसी Static Member को Define करते हैं, तो वह Member भी Exactly उसी तरह से Behave करता है, जिस तरह से कोई सामान्य Static Member Behave करता है।

<?php
	trait Counter {
	    public function increment() {
	        static $c = 0;
	        $c = $c + 1;
	        echo "$c\n";
	    }
	}
	
	class C1 {
	    use Counter;
	}
	
	class C2 {
	    use Counter;
	}
	
	$obj1 = new C1(); 
	$obj1->increment(); 
	
	$obj2 = new C2(); 
	$obj2->increment(); // echo 1
?>

जैसाकि सामान्य Function में Declare किया गया Static Data Member Behave करता है, इस Program में भी increment() Method को जितनी भी बार Call किया जाता है, $c Static Variable का पिछला मान Live रहता है, जबकि Method Call होने पर Create होता है व Execution के बाद Destroy हो जाता है।

Static Methods

Static Variable की तरह हम किसी Trait में Static Method को भी Create कर सकते हैं और ये Static Method Exactly सामान्य Static Method की तरह ही व्यवहार करता है।

यानी हमें Trait के अन्दर Define किए गए Static Method को भी Access करने के लिए Class के नाम के साथ Scope Resolution Operator का प्रयोग करके Method के नाम को Specify करना होता है।

<?php
	trait StaticExample {
	    public static function doSomething() {
	        return 'Doing something';
	    }
	}
	
	class Example {
	    use StaticExample;
	}
	
	echo Example::doSomething();
?>

//Output
   Doing something

जैसाकि हम देख सकते हैं कि इस Program में भी Static Method Exactly उसी तरह से Call हो रहा है, जिस तरह से किसी सामान्य Function में होता है और ऐसा इसीलिए हो रहा है, क्योंकि Internally Trait के सारे Codes सामान्य Codes की तरह ही Expand होते हैं।

Trait Properties

Traits में हम सामान्य Class के Data Members की तरह ही Properties यानी Data Members को भी Define कर सकते हैं।

<?php
	trait PropertiesTrait {
	    public $x = 1;
	}
	
	class PropertiesExample {
	    use PropertiesTrait;
	}
	
	for($i=0; $i<5; $i++){
		$example = new PropertiesExample;
		Echo $example->x;
	}
?>

उपरोक्त Program में हमने PropertiesExample Class में किसी Data Member को Declare नहीं किया है, फिर भी हम $x नाम के Data member को Access कर पा रहे हैं। ऐसा इसलिए हो रहा है क्योंकि हालांकि हमने Class के अन्दर इस Variable को Declare नहीं किया है, लेकिन Trait में Define किया गया Variable भी उस समय Class में ही Expand होता है, जब हम किसी Trait को किसी Class में Use करते हैं।

यानी Trait में Declare किया गया Variable उस Class के Data Member की तरह Use होता है, जिसमें Trait को Use किया जाता है।

PHP Autoload
PHP Type Hinting

PHP in Hindiये Article इस वेबसाईट पर Selling हेतु उपलब्‍ध EBook PHP in Hindi से लिया गया है। इसलिए यदि ये Article आपके लिए उपयोगी रहा, तो निश्चित रूप से ये पुस्तक भी आपके लिए काफी उपयोगी साबित होगी। 

PHP in Hindi | Page: 647 | Format: PDF

BUY NOW GET DEMO REVIEWS