Jump to content

Function that returns several values, how to OOP call it ?


Dzherzinsky

Recommended Posts

Hello

 

 

I am on to OOP now and I dont know how to write the syntax to print the results I want

 

The scenario is I have the abstract class, its subclass and then the object that calls the subclass, all in different files.

 

So:

 

part of the subclass reads:

 


function __construct($v1, $v2, $v3) {

	$this->speed[] = $v1;  // I dont like this either, it is not elegant. I tried to put an array as argument of the constructor and send the parameters 
	$this->speed[] = $v2;  // from the object being created, but it did not work, so I leave it like this for now, but I would have preferred to put that 
	$this->speed[] = $v3;  // array and then populate it by some looping.

}

// METHOD TO REPORT TABLE OF ACCELERATION


   public function acceleration() {

   return $this->acceleration1 =	($this->speed[1] - $this->speed[0])/5;

          // I actually need to return the other two speed differences from the other stages, but as you know, once the first return acts, it exits the function
         // so sure this "return" has to be abandoned and the results of the function have to be printed otherwise. That is the question.

   }

 

===================================

And now from the Object file I am trying to call the function, but of course, I only get one value, even if I write 3 times return

 


$objeto = new Motorbike($v1, $v2, $v3);

echo '<p>The speeds are  ' . $objeto->acceleration() . '</p>';  // Yes, this call works, of course, but that is about it. I cant print any other result.

 

Thanks a lot

 

 

 

 

 

 

 

Link to comment
Share on other sites

It's all preference, both of these are technically correct

 

<?php

$obj = new vehicle(10, 60, 90);

echo '<pre>';

// Access using $acc1[0], $acc1[1]
$acc1 = $obj->accel_array();
print_r( $acc1 );

// Access using $acc2->accel_1, $acc2->accel_2
// You can even simply use $obj->accel_object()->accel_1,
// $obj->accel_object()->accel_2, etc
$acc2 = $obj->accel_object();
print_r( $acc2 );

echo '</pre>';

class vehicle {

private $speed = array();

public function __construct( $a,$b,$c ) {
	$this->speed[] = $a;
	$this->speed[] = $b;
	$this->speed[] = $c;
}

public function accel_array() {
	$return = array();
	$return[] = $this->speed[1] / $this->speed[0];
	$return[] = $this->speed[2] / $this->speed[0];
	return $return;
}

public function accel_object() {
	return new accel($this->speed[0],$this->speed[1],$this->speed[2]);
}

}

// Better solution if there's acceleration-specific methods you'd like to create that emcompass
// all types of vehicles. It's a form of separating logic.
class accel {
public $accel_1, $accel_2;
public function __construct( $a,$b,$c ) {
	$this->accel_1 = $b / $a;
	$this->accel_2 = $c / $a;
}
}

?>

 

I like the idea of giving something like acceleration it's own class. You can keep all of your acceleration methods in that class, rather than clutter up the vehicle class.

Link to comment
Share on other sites

 

 

Thank you, I ll take it from there. Interesting was to see how you managed to return several results, you just created an array and hauled all the data there, and then returned the array instead of a single scalar variable (why didnt I think about that ?)

 

regards

Link to comment
Share on other sites

 

Hello again

 

but, you are placing all the variables one after one in the parentheses of the constructor. One of my questions was to put instead an array as a parameter of the constructor.

 

You wrote this one

 


public function __construct( $a,$b,$c ) {
	$this->speed[] = $a;
	$this->speed[] = $b;
	$this->speed[] = $c;

 

the question is if I could do something like this, but it aint working

 


function __construct($distance) {   // where $distance is an array that will get in a lot all the params sent by the object in another file

	for($i = 1; $i<=3;$i++ ){     // here below I send distances made every 10 seconds. That will give me the speed at that point

		$this->speed[$i] = ($this->distance[$i])/($i*10);  



		}


	}

and below this code, I would get the acceleration out of the speed differences per time moment

 

 

 

 

Link to comment
Share on other sites

 

 

yes, that is what I asummed and that is why I went straight to do that. In the code snippet I am just doing that, but the return I get is 0.

 

this is the object calling from another file

 

 


$v1 = 10;
$v2 = 20;
$v3 = 40;

$object = new Motorbike($v1, $v2, $v3);

echo '<p>The speeds are  ' . $object->acceleration() . '</p>';


 

and well, I just reduced it to the minimum for testing purposes  here is the full code of both the construct and one method. I call to that method with the object

 


class Motorbike extends Vehicle {

private $wheels, $price, $builtyear, $seats;

private $distance = array(); 
private $speed = array();


function __construct($distance) { 

	for($i = 1; $i<=3;$i++ ){   

$this->speed[$i] = ($this->distance[$i])/($i*10); // this gets the distances sent by the object, divides them by different time points gets the speed



		}


	}





// METHOD TO REPORT TABLE OF ACCELERATION


   public function acceleration() {
   	
   	$devuelve = array();
   	
   	echo count($distance);

   return $this->devuelve = ($this->speed[2] - $this->speed[1])/5;  // and the acceleration (if constant) is difference of speed at different time points
                                                     // of course, I want for all array elements, I just chose one pair above for testing

   }

}	
   


Link to comment
Share on other sites

Your code doesn't make allot of sense. Your __construct expects a single argument, you pass it 3.

 

From there, you don't actually use any of the arguments within the __construct. Your acceleration() method then goes on to try and echo a variable ($distance) which has not been defined and also tries to access indexes within the $this->speed array which don't appear to have been set anywhere within any code you have posted.

Link to comment
Share on other sites

You are still trying to pass 3 variables into the constructor and therefore needs 3 variables to receive it (as far as I know) like Thorpe mentioned.

You could make the array before passing it to your constructor though.

 

$v1 = 10;
$v2 = 20;
$v3 = 40;

$distance = array($v1, $v2, $v3);

$object = new Motorbike($distance);

echo '<p>The speeds are  ' . $object->acceleration() . '</p>';

 

class Motorbike extends Vehicle {
private $wheels, $price, $builtyear, $seats;
private $distance;
private $speed = array();


function __construct($distance) {
	$this->distance = $distance;
	for($i = 1; $i<=3;$i++ ){   		
		$this->speed[$i] = ($distance[$i])/($i*10); // this gets the distances sent by the object, divides them by different time points gets the speed
	}
}

public function acceleration() {
   	$devuelve = array();

   	echo count($this->distance);
	return $devuelve = ($this->speed[2] - $this->speed[1])/5;  // and the acceleration (if constant) is difference of speed at different time points
    }	
}

Link to comment
Share on other sites

Hi

 

well let's see

 

 

1)Your code doesn't make allot of sense. Your __construct expects a single argument, you pass it 3.

 

but this is what I have been talking about all the time, if $distance is an array, then I can pass it several parameters, at least that is what I thought, that is why it is an array for.

 

 

2) From there, you don't actually use any of the arguments within the __construct. Your acceleration() method then goes on to try and echo a variable ($distance) which has not been defined

 

a) I mean, you dont need to predefine variables in php, you can use them on the fly, cant you ?

 

b) and also tries to access indexes within the $this->speed array which don't appear to have been set anywhere within any code you have posted.

 

Where not ? this is what I was trying to achieve precisely, to set the variable through the loop of the array which is the parameter of the construct

$this->speed[$i] = ($this->distance[$i])/($i*10);

 

So, as you can see it makes sense what I tried. Another completely different thing is that the syntax is incorrect and the assumptions of how the code should work can be incorrect, but there were not random pieces here and there

 

Link to comment
Share on other sites

They are random enough to not make sense.

 

1) To pass an array to a method is no different to any other variable. eg;

 

function foo($arr) {
  foreach ($arr as $val) {
    echo $val;
  }
}

foo(array('a', 'b', 'c'));

// or
$a = array('a', 'b', 'c');
foo($a);

 

2) Functions (or methods within a class) have there own scope. Variables created outside of functions do not exist within a function. Same goes for classes. This is why the features are useful.

 

3) I missed in your code.

Link to comment
Share on other sites

Sorry messed up in my comment there, edit your acceleration function

 

public function acceleration() {
   	echo count($this->distance);
return ($this->speed[2] - $this->speed[1])/5;  // and the acceleration (if constant) is difference of speed at different time points
}

Link to comment
Share on other sites

I mean, on page 302 of the book PHP 5 advanced by Larry Ullman

 

there is a code snippet which goes like this, and the attributes are declared outside the functions and are used within the functions. That is what the $this is for

 

That code snippet reads

 

 

class Triangle extends Shape {


private $sides = array ();
private $perimeter = NULL;

then comes the constructor

 

finishes the constructor

 

and then there is a method like this

 

 

public function get_perimeter () {

return $this->perimeter;

}

 

So, I am not using that attribute in any way different that is used in the book. I d rather say that variables declared within a function, yes, are local to it and do die after the function finishes, but attributes declared outside functions can be used by these, in fact, that is how everything goes, you declare the variables, you declare the construct and then you declare the functions.

 

I am a newbie so I am not in the least pretending to argue, I was just believing it was like this. Anyway, I ll return to the book again.

 

thanks

 

 

 

Link to comment
Share on other sites

 

 

1) To pass an array to a method is no different to any other variable. eg;

 

That is a different matter. The issue herein is whether when you create an object and the constructor automatically gets the parameters that the object had, if the array that is Already in the constructor parenthesis as a parameter, would get the list of values that were as parameters of the object. As I am seeing the answer is no. I did a sizeof($distance) to see what it got, and it gets nothing but 1 single value, not the other two aswell from the list of arguments of the object.

 

==========================================================================================================

 

 

function foo($arr) {
  foreach ($arr as $val) {
    echo $val;
  }
}

foo(array('a', 'b', 'c'));

// or
$a = array('a', 'b', 'c');
foo($a);

 

2) Functions (or methods within a class) have there own scope. Variables created outside of functions do not exist within a function. Same goes for classes. This is why the features are useful.

 

3) I missed in your code.

Link to comment
Share on other sites

Well what you wrote there is correct.

 

You don't strictly need to use a constructor though.

Personally I only use constructors when I want to pass predefined values from a database to an object. (Kind of like I need to set class variables before I start using it).

If I am passing outside values into my class I usually just make methods for it.

 

class myClass {
        public classVariable;   // These are local to the class and can be used by all methods/functions

        public function myMethod($localMethodVar) {
                $localMethodVar2 = $localMethodVar;   // These are local to the method and can only be used within the method/function
                $this->classVariable = $localMethodVar2;   // This assigns local method variables to classVariable
        }

        public function myMethod2() {
               $localMethodVar = $this->classVariable;   // This takes classVariable previously assigned a value by myMethod and puts it in localMethodVar local to myMethod2
        }
}

 

In your original code there is some variables being called that is outside of their scopes etc.

As you pointed out in your last reply, when creating a class one should keep some points in mind.

Class variables shared by several methods should be defined beforehand even if they are empty.

 

classVariables are local to the class and can be used by all methods in your class.

methodVariables are local to the method and is only used in the method.

 

if you want to use methods from another class file after the object has been created you can call functions by first declaring the object.

global $object;

then you can call a method from that object using

$object->objectMethod();

 

This is how I understand it through my own studies.

Once the object oriented aspects dawns on your completely a whole new world opens up in programming. (When I burst that bubble it was definitely eureka going on)

 

If this doesn't really help you any i'm sorry for creating a bigger confusion.

 

Good luck onwards!

Link to comment
Share on other sites

Whoa, timeout.  'global' should never be used in any context, and it's especially egregious in OOP.  It ties your object/method/function/whatever to the context in which it's used, which is exactly what you don't want to do.  The whole idea behind OOP is to make modular code.  Code cannot be modular if it's bound to a particular context.

 

Second, in most cases, you don't want your fields to be public.  Methods?  Sure.  But your fields should be protected or private, depending on whether or not you expect to extend your class.  There are exceptions, but private/protected fields should be your default setting.

 

Third, custom constructors, like SnapGravy said, aren't mandatory.  A constructor is always invoked when an object is instantiated, as PHP (and, really, most/all languages with objects) have a default constructor which handles instantiation.  When you write a custom constructor, your code is executed in addition to the default constructor.

 

So, with all that said, can you actually show the class code you're having trouble with in its entirety?  I can't tell what specific problem you're having with your code as your examples seem canned and/or haphazard.  Seeing the complete picture of what you're trying to do will help me help you.

Link to comment
Share on other sites

Whoa, timeout.  'global' should never be used in any context, and it's especially egregious in OOP.  It ties your object/method/function/whatever to the context in which it's used, which is exactly what you don't want to do.  The whole idea behind OOP is to make modular code.  Code cannot be modular if it's bound to a particular context.

 

I'm kind of happy that you mention this because I really don't like passing global's like this either. But from countless searches I have found no other way to create communication between two classes except for extending the class. I could do this but if I have multiple classes I cannot extend them all.

 

I could of course write the methods I use from other classes inside the actual class but then I will end up having duplicate methods in several different classes which for me is bad because if I want to change the method I need to do this over all the classes making creating the method in the first place moot.

 

I am not an expert though, and I would be extremely happy if you have a pointer for me in how to go about this problem sharing methods from multiple classes. That's been the one point about OOP that's baffled my mind and the only way I found a way to do that was to global the object so I can use it within a class.

 

(Not trying to hijack this topic with my own question but since its in the spirit of learning and were already on the subject. Hope you don't mind OP).

Link to comment
Share on other sites

Objects can contain other objects, which is known as composition, and is generally a better way to go in most cases than inheritance.  Objects can be passed as parameters in methods.  Objects can invoke another object's methods if they're public and in scope.  Static methods exist, which are class-based rather than instance-based.

Link to comment
Share on other sites

 

 

Hello

 

well I am going nuts trying to return the full array of values for printing when I call the function from another file.

 

Here is one file:

 

<?php


class Motorbike extends Vehicle {
protected $bikes_speed = array();		

public function speed ($d1, $d2, $d3){

$bikes_speed[] = $v1 = $d1/10;
$bikes_speed[] = $v2 = $d2/10;
$bikes_speed[] = $v3 = $d3/10;


return $bikes_speed();  // Fatal error: Function name must be a string in C:\xampp\htdocs\code\Motorbike.php on line 14

}

// METHOD TO REPORT TABLE OF ACCELERATION

   public function acceleration() {
   	
   echo "not defined yet";

   }

}	

?>

 

and here is the calling object and function from the other file

 


<?php



require_once 'vehicle.php';
require_once 'Motorbike.php';


$v1 = 50;
$v2 = 20;
$v3 = 600;

$suzuky_hayabusha = new Motorbike();


$suzuky_hayabusha->speed($v1, $v2, $v3);

echo '<p>The speeds are  ' . $suzuky_hayabusha->speed($v1, $v2, $v3) . '</p>';

foreach ($bikes_speed as $value){


echo $value;
}


?>

 

Link to comment
Share on other sites

You're confused about class variables, arrays, and how they work.  Try:

 

class Motorbike extends Vehicle
{
   protected $bikes_speed = array();		

   public function speed ($d1, $d2, $d3)
   {
      // the 'this' keyword denotes that the variable $bikes_speed belongs to the current object
      $this->bikes_speed[] = $d1/10;
      $this->bikes_speed[] = $d2/10;
      $this->bikes_speed[] = $d3/10;

      return $this->bikes_speed;
   }
}

 

In your script:

 

$v1 = 50;
$v2 = 20;
$v3 = 600;

$suzuki = new Motorbike();
$speeds = $suzuki->speed($v1, $v2, $v3);

echo "Speeds are: ";

foreach($speeds as $speed)
{
   echo $speed . "<br />";
}

 

That said, you could simplify your speed method by accepting an array:

 

public function speed($speeds)
{
   foreach($speeds as $speed)
   {
      $this->bikes_speed[] = $speed/10;
   }

   return $this->bikes_speed;
}

 

But, really, before you even attempt to play with OOP, you need to get the basics of PHP down first.  If you can't handle 1-dimensional arrays, foreach loops, and how to echo values correctly, you won't have a chance with objects.

Link to comment
Share on other sites

 

 

thank you a lot

 

I completed the book of PHP long ago, but the problem is that whatever I learn last week, I cant remember it today (age)

 

and as per the simplification of the method accepting an array, that was pretty much the first question I asked right at the beginning of the thread if a constructor (at the time) could have an array as argument as I was sending several arguments at the instantiaton moment creating an object, but while I do forget what my name is or what I had for breakfast, I realized I came across a very common issue which is returning several values from a function (which cant be) and how to work around it with array and also calling from different objects and files.

 

Believe it or not, I coded entirely www.matchandtravel.net and if you look at it it does have some nice JQUERY stuff and AJAX

 

thanks a lot. I will do my best to get this coding that you did (it works, I tried it) into my head and keep it in.

 

best regards

Link to comment
Share on other sites

 

Hello

 

 

the first version you wrote works.

 

But, have you tested the second, the one that has the speed method accepting the array ?

 

I get Warning: Invalid argument supplied for foreach() in C:\xampp\htdocs\code\Motorbike.php on line 21

 

and that line corresponds to

 

foreach($speeds as $speed) which is baffling to me because your code does seem completely correct here too

 

 

 

 

 

 

 

 

You're confused about class variables, arrays, and how they work.  Try:

 

class Motorbike extends Vehicle
{
   protected $bikes_speed = array();		

   public function speed ($d1, $d2, $d3)
   {
      // the 'this' keyword denotes that the variable $bikes_speed belongs to the current object
      $this->bikes_speed[] = $d1/10;
      $this->bikes_speed[] = $d2/10;
      $this->bikes_speed[] = $d3/10;

      return $this->bikes_speed;
   }
}

 

In your script:

 

$v1 = 50;
$v2 = 20;
$v3 = 600;

$suzuki = new Motorbike();
$speeds = $suzuki->speed($v1, $v2, $v3);

echo "Speeds are: ";

foreach($speeds as $speed)
{
   echo $speed . "<br />";
}

 

That said, you could simplify your speed method by accepting an array:

 

public function speed($speeds)
{
   foreach($speeds as $speed)
   {
      $this->bikes_speed[] = $speed/10;
   }

   return $this->bikes_speed;
}

 

But, really, before you even attempt to play with OOP, you need to get the basics of PHP down first.  If you can't handle 1-dimensional arrays, foreach loops, and how to echo values correctly, you won't have a chance with objects.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.