I would like to know whether there's a way to chain methods on a newly created object in PHP?
Something like:
class Foo {
public function xyz() { ... return $this; }
}
$my_foo = new Foo()->xyz();
Anyone know of a way to achieve this?
I would like to know whether there's a way to chain methods on a newly created object in PHP?
Something like:
class Foo {
public function xyz() { ... return $this; }
}
$my_foo = new Foo()->xyz();
Anyone know of a way to achieve this?
You could keep a list of things that needs to be initialised and whether they have been so in this instance or not. Then check the list each time you use one of the initialisation methods. Something like:
class O {
private $init = array
( 'red' => false
, 'green' => false
, 'blue' => false
);
private function isInit() {
$fin = true;
foreach($this->init as $in) {
$fin = $fin && $in;
}
return $fin;
}
public function green($n) {
$this->init['green'] = true;
if($this->isInit()) {
$this->insert();
}
}
public function red($n) {
$this->init['red'] = true;
if($this->isInit()) {
$this->insert();
}
}
public function blue($n) {
$this->init['blue'] = true;
if($this->isInit()) {
$this->insert();
}
}
private function insert() {
echo "wheen";
}
}
But personally I think this would be more hassle then it's worth. Better imo
to expose your insert
method and let the user of you code tell when the
initialisation is finished. So something that should be used like:
$o->red(1)->green(2)->blue(0)->insert();
-update-
If it's the case that it's impossible to predict what functions need to be called you really do need to be explicit about it. I can't see a way around that. The reason is that php really can't tell the difference between
$o1 = new A();
$o2 = $o1->stuff();
and
$o2 = (new A())->stuff();
In a language that allows overloading =
I guess it would be possible but really
really confusing and generally not a good idea.
It is possible to move the explicit part so that it's not at the end of the call chain, but I'm not sure if that would make you happier? It would also go against your desire to not use another instance. It could look something like this:
class O {
public function __construct(InitO $ini) {
// Do stuff
echo "Wheen";
}
}
class InitO {
public function red($n) {
return $this;
}
public function green($n) {
return $this;
}
public function blue($n) {
return $this;
}
}
$o = new O((new InitO())->red(10)->red(9)->green(7));
You can of course use just one instance by using some other way of wrapping but the only ways I can think of right now would look a lot uglier.
We have an extension method to do exactly this in MoreLINQ. You can look at the implementation there, but basically it's a case of iterating through the data, remembering the maximum element we've seen so far and the maximum value it produced under the projection.
In your case you'd do something like:
var item = items.MaxBy(x => x.Height);
This is better (IMO) than any of the solutions presented here other than Mehrdad's second solution (which is basically the same as MaxBy
):
Max
value and then finding the first element with that value is O(n), but iterates over the sequence twice. Where possible, you should use LINQ in a single-pass fashion.In general, if something is documented as being a constructor, use new
with it. But in this case, RegExp
has a defined "factory" behavior for the situation where you've called it as a function instead. See Section 15.10.3 of the ECMAScript (JavaScript) specification (that links to the outgoing spec; the section number is the same in the new spec, which you can download from the ECMA front page [on the right-hand side]; I don't want to directly link to a ~4MB PDF file):
15.10.3 The RegExp Constructor Called as a Function
15.10.3.1 RegExp(pattern, flags)
If pattern is an object R whose [[Class]] property is "RegExp" and flags is undefined, then return R unchanged. Otherwise call the RegExp constructor (15.10.4.1), passing it the pattern and flags arguments and return the object constructed by that constructor.
You can actually define your own JavaScript constructor functions to allow omitting the new
keyword (by detecting they've been called as a function instead, and turning around and calling themselves correctly), but I wouldn't suggest it as it leads to misleading code.
This was an issue with saving the user
. I updated my create
action in the Dwellings
controller to to force a save of the user
using user.save!
to break the application and get an explicit error. Rails complained of a missing password
(and password length) and password_confirmation
. I am enforcing a presence
validation on both password
and password_confirmation
as well as a length
validation on password
in my User
model. I updated these validations to be enforced only on create
. This solved the issue. With the validations no longer being enforced on user.save
, the dwelling_id
was successfully added to the user
record. The newly implemented code is below.
#dwellings_controller.rb
...
def create
@dwelling = current_user.properties.build(params[:dwelling])
if @dwelling.save
current_user.dwelling = @dwelling
if current_user.save
flash[:success] = "Woohoo! Your dwelling has been created. Welcome home!"
else
flash[:notice] = "You have successfully created a dwelling, but something prevented us from adding you as a roomie. Please email support so we can try to correct this for you."
end
redirect_to current_user
else
render 'new'
end
end
...
--
#user.rb
...
validates :password, presence: { :on => :create }, length: { minimum: 6, :on => :create }
validates :password_confirmation, presence: { :on => :create }
In PHP 5.4+, the parser's been modified so you can do something like this
Wrap the instantiation in parenthesis, and chain away.
Prior to PHP 5.4, when you're using the
syntax, you can't chain a method call off the instantiation. It's a limitation of PHP 5.3's syntax. Once an object is instantiated, you can chain away.
One method I've seen used to get around this is a static instantiation method of some kind.
By wrapping the call to new in a static method, you can instantiate a class with method call, and you're then free to chain off that.