Returning a Value in Constructor Function of a Class

Returning a value in constructor function of a class

Constructors don't get return values; they serve entirely to instantiate the class.

Without restructuring what you are already doing, you may consider using an exception here.

public function __construct ($identifier = NULL)
{
$this->emailAddress = $identifier;
$this->loadUser();
}

private function loadUser ()
{
// try to load the user
if (/* not able to load user */) {
throw new Exception('Unable to load user using identifier: ' . $this->identifier);
}
}

Now, you can create a new user in this fashion.

try {
$user = new User('user@example.com');
} catch (Exception $e) {
// unable to create the user using that id, handle the exception
}

What is the return value of an ES2015 constructor function?

According to MDN's reference on the new operator:

When the code new Foo(...) is executed, the following things happen:

  1. A new object is created, inheriting from Foo.prototype.
  2. The constructor function Foo is called with the specified arguments, and with this bound to the newly created object. new Foo is equivalent to new Foo(), i.e. if no argument list is specified, Foo is called without arguments.
  3. The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)

(Emphasis mine.) So it seems that the return value of the constructor function is an object, more specifically an instance of the class.

Further research showed that the return value of the constructor can be overridden by explicitly returning any object from within the constructor function (though non-object return values will be ignored, in which case the default of the newly created object reference is used.) I could not find anything to indicate that ES2015 constructors are any different than constructors prior to ES2015 classes.

This Stack Overflow post was very helpful in researching the above, particularly this article it contained a link to, though since constructor did not appear in the code in either the question nor the article, with my limited understanding of constructors that I had going into researching this they did not seem at first to answer my question. Hopefully this may clarify for others in the same situation.

Edit: The veracity of MDN's information was called into question in comments, so I researched a more definitive source. The ECMA specification says of constructors:

A constructor is an object that supports the [[Construct]] internal method.

The [[Construct]] internal method is then defined as follows:

Signature: (a List of any, Object) → Object

Description: Creates an object. Invoked via the new or super operators. The first argument to the internal method is a list containing the arguments of the operator. The second argument is the object to which the new operator was initially applied. Objects that implement this internal method are called constructors. A function object is not necessarily a constructor and such non-constructor function objects do not have a [[Construct]] internal method.

The spec states that in describing signatures such as the one above, the following convention is used: "If an internal method explicitly returns a value, its parameter list is followed by the symbol “→” and the type name of the returned value."

So, to summarize, based on the ECMA specification as quoted above, yes, constructor functions definitively do in fact return objects.

Java: How can a constructor return a value?

What you've defined isn't actually a constructor, but a method called Const. If you changed your code to something like this, it would work:

Const c = new Const();
System.out.println( c.Const( "Hello!" ) );

If no specific constructor is explicitly defined, the compiler automatically creates a no-argument constructor.

Changing the return value of a constructor

A class constructor returns the value of this when it gets called by the new keyword.

See What is the 'new' keyword in JavaScript? and How does the new operator work in JavaScript? for details.

Can we change the return value to something else?

Yes, as long as it is an object, you can override the default by using return - as you did in your example code. See What values can a constructor return to avoid returning this? and What is returned from a constructor? for how that works exactly.

If yes, is it a bad practice?

Yes. Having new Car return a function and not a Car instance is weird and unexpected. People do not do this every day, and they shouldn't start doing it :-)

The only exception is the singleton pattern (which of course is problematic itself), where the constructor may return the singleton instance instead of a new one. (There are however other ways to write JS code for creating singletons, which avoid constructors altogether.)

What is returned from a constructor?

I found this great link:

JavaScript: Constructor Return Value

The second piece of magic eluded to above is the ability for a
constructor to return a specific, possibly pre-existing object, rather
than a reference to a new instance. This would allow you to manage the
number of actual instances yourself if needed; possibly for reasons of
limited resources or whatnot.

var g_deebee = new Deebee();
function Deebee() { return g_deebee; }
var db1 = new Deebee();
var db2 = new Deebee();
if (db1 != db2)
throw Error("JS constructor returned wrong object!");
else console.log('Equal');

Constructor returning value?

Indeed you are correct. Nothing can be done with the return value of a constructor (aside from using the Object it created).

So no, you aren't missing anything, it's the developer who wrote that code who is.

It is technically possible to use return values from constructors, if you call the function directly

$obj->__construct();

That would allow you to use the constructor's return value. However, that is highly uncommon and fairly not recommended.

What if I write return statement in constructor?

Yes, using return statements in constructors is perfectly standard.

Constructors are functions that do not return a value. The family of functions that do not return a value consists of: void functions, constructors and destructors. It is stated in 6.6.3/2 in the C++ standard. The very same 6.6.3/2 states that it is illegal to use return with an argument in a function that does not return a value.

6.6.3 The return statement

2 A return statement without an
expression can be used only in
functions that do not return a value,
that is, a function with the return
type void, a constructor (12.1), or a
destructor (12.4). A return statement
with an expression of non-void type
can be used only in functions
returning a value; the value of the
expression is returned to the caller
of the function.

Additionally, 12.1/12 states that

12.1 Constructors

12 No return type (not even void) shall
be specified for a constructor. A
return statement in the body of a
constructor shall not specify a return
value.

Note, BTW, that in C++ it is legal to use return with an argument in a void function, as long as the argument of return has type void

void foo() {
return (void) 0; // Legal in C++ (but not in C)
}

This is not allowed in constructors though, since constructors are not void functions.

There's also one relatively obscure restriction relevant to the usage of return with constructors: it is illegal to use return in function-try-block of a constructor (with other functions it is OK)

15.3 Handling an exception

15 If a return statement appears in a
handler of the function-try-block of a
constructor, the program is ill formed.

Is RETURN from constructor necessary when creating object with new

No, returning this is not necessary, but it is valid. If the returned value is an object, new will return that object instead of the newly created object.

See points 11.2.2 and 13.2.2 of ECMAScript 5:

The new operator calls the internal [[Construct]] method on the constructor (usually a function):

11.2.2 The new Operator

The production NewExpression : new NewExpression is evaluated as follows:

  1. Let ref be the result of evaluating NewExpression.
  2. Let constructor be GetValue(ref).
  3. If Type(constructor) is not Object, throw a TypeError exception.
  4. If constructor does not implement the [[Construct]] internal method, throw a TypeError exception.
  5. Return the result of calling the [[Construct]] internal method on constructor, providing no arguments (that is, an empty list of arguments).

The [[Construct]] internal method of functions is described in point 13.2.2:

13.2.2 [[Construct]]

When the [[Construct]] internal method for a Function object F is called with a possibly empty list of arguments, the following steps are taken:

  1. Let obj be a newly created native ECMAScript object.
  2. Set all the internal methods of obj as specified in 8.12.
  3. Set the [[Class]] internal property of obj to "Object".
  4. Set the [[Extensible]] internal property of obj to true.
  5. Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
  6. If Type(proto) is Object, set the [[Prototype]] internal property of obj to proto.
  7. If Type(proto) is not Object, set the [[Prototype]] internal property of obj to the standard built-in Object prototype
    object as described in 15.2.4.
  8. Let result be the result of calling the [[Call]] internal property of F, providing obj as the this value and providing the argument list passed into [[Construct]] as args.
  9. If Type(result) is Object then return result.
  10. Return obj.


Related Topics



Leave a reply



Submit