Выезд Соединение (SQL) на Википедию
оставленный / правильное (внешнее) соединение - Учитывая две таблицы, возвращает все строки, которые существуют или в левой или правой таблице Вашего соединения, плюс строки с другой стороны будет возвращен, когда пункт соединения является соответствием или пустым указателем, будет возвращен для тех столбцов
Полный Внешний - Учитывая две таблицы, возвращает все строки и возвратится, аннулирует, когда любой левый или правый столбец не там
Перекрестные объединения - Декартово соединение и может быть опасным если не используемый тщательно
Ик. У Стевана есть очень веский аргумент, что новый
всегда должен
вернуть экземпляр класса. Все остальное сбивает с толку новых людей, которые учатся
систему.
Возможно, вы захотите взглянуть на MooseX :: AbstractFactory . Если у вас это не сработает, то:
package FooBar;
use Moose;
has [qw(SUBCLASS MSG)] => ( is => 'ro', required => 1);
sub create_instance {
return $self->package->new(message => $self->msg);
}
package FooBar::Object;
use Moose;
has msg => ( is => 'ro', required => 1);
sub Hi {
my $self = shift;
print "Hi, I'm a " . ref($self) ." and I say [". $self->MSG()."]\n";
}
package Foo;
use Moose;
extends qw(FooBar::Object);
package Bar;
use Moose;
extends qw(FooBar::Object);
package main;
or my $line (<DATA>) {
my ($case,$msg)=split(/[\n\r,]\s*/,$line);
FooBar->new(SUBCLASS=>$case,MSG=>$msg)->create_instance->Hi
}
__DATA__
Foo, First Case
Bar, Second Case
Конечно, есть много других способов реализовать ту же концепцию в Moose. Не зная специфики проблемы вашей предметной области, трудно сказать, что что-то вроде MooseX :: Traits не было бы лучше:
package Foo;
use Moose;
with qw(MooseX::Traits);
package Bar;
use Moose;
with qw(MooseX::Traits);
package Messaging;
use Moose::Role;
has msg => ( is => 'ro', required => 1);
sub Hi {
my $self = shift;
print "Hi, I'm a " . ref($self) ." and I say [". $self->MSG()."]\n";
}
package main;
use strict;
Foo->with_traits('Messaging')->new( msg => 'First Case')->Hi;
Это примерно то, что имел в виду другой плакат об использовании решения на основе ролей.
Вы можете просто сделать:
$case->new( MSG => $msg )->Hi();
Если это легче или лучше, решать вам.
Итак, объект уже создан, когда вызывается BUILD
, поэтому я бы сказал
sub BUILD {
my $self = shift;
return bless $self, $self->SUBCLASS;
}
Вы всегда можете захотеть переключиться с модели на основе наследования. в ролевую модель, в которой вы создаете нужный объект (вместо передачи класса в фабричный класс), а затем применяете общую роль.
Просто используйте другой объект фабрики для создания объектов этого класса.
Проще, гибче, надежнее и т. Д.
my $ factory = Factory-> new (... заводские параметры ...);
my $ object = $ factory-> new_object (... различные параметры ...);
где new_object
может анализировать параметры и принимать решения как по данным внутри $ factory
, так и по данным из этих параметров.
Когда вы понимаете, что вам понадобятся созависимые объекты на следующем этапе ищите инверсию структуры управления.
Просто примечание к некоторым ответам:
Вызов bless
в BUILD или где-либо еще за пределами внутреннего устройства MOP всегда неприемлем. (Если вам необходимо выполнить повторное восстановление, есть Class :: MOP :: Class-> rebless_instance
!)
Я второй совет не позволять new
возвращать что-либо, кроме экземпляра из __ ПАКЕТ __
. Если вам нужен метод, который создает экземпляр чего-то, назовите это как-нибудь еще. Пример:
class Message {
method new_from_string(Str $msg){
my ($foo, $bar, $baz) = ($msg =~ /<...>/); # blah blah blah
my $class = "Message::${foo}::$baz";
Class::MOP::load_class($class);
return $class->new( bar => $msg );
}
}
Затем, если вы хотите создать буквальное сообщение:
Message->new( whatever => 'you want' );
Если вы хотите проанализировать строку и вернуть правильный подкласс сообщения:
Message->new_from_string( 'OH::Hello!' );
Наконец, если нет смысла создавать экземпляр Message, то он не должен быть классом. Это должна быть роль.
Вы, конечно, можете управлять строительством с помощью другого объекта. Просто убедитесь, что этот другой объект отвечает только за понимание формата строки, например, а не за внутреннюю структуру сообщения:
class MessageString {
has 'string' => ( initarg => 'string', reader => 'message_as_string' );
method new_from_string(ClassName $class: Str $string) {
return $class->new( string => $string );
}
method as_message_object {
# <parse>
return Message::Type->new( params => 'go here', ... );
}
}
role Message { ... }
class Message::Type with Message { ... }
Теперь вас больше не беспокоит наличие какого-то «суперкласса», отвечающего за создание «подклассов», что, на мой взгляд, лучше дизайн. (Помните, что MessageString не имеет особой власти над классами, которые выполняют "Message". Это ключ здесь; он отвечает только за понимание строковых сообщений.)
В любом случае, теперь вы просто:
my $data = <>; # Yup, I called it $data. Sorry, Andy Lester.
my $parsed = MessageString->new_from_string( $data );
my $message = $parsed->as_message_object;
$message->interact_with
(Вы знаете "MVC" "? Это похоже.)
MessageString не имеет особой власти над классами, выполняющими «Message». Это ключ здесь; он отвечает только за понимание строковых сообщений.)В любом случае, теперь вы просто:
my $data = <>; # Yup, I called it $data. Sorry, Andy Lester.
my $parsed = MessageString->new_from_string( $data );
my $message = $parsed->as_message_object;
$message->interact_with
(Вы знаете "MVC"? Это похоже.)
MessageString не имеет особой власти над классами, выполняющими «Message». Это ключ здесь; он отвечает только за понимание строковых сообщений.)В любом случае, теперь вы просто:
my $data = <>; # Yup, I called it $data. Sorry, Andy Lester.
my $parsed = MessageString->new_from_string( $data );
my $message = $parsed->as_message_object;
$message->interact_with
(Вы знаете "MVC"? Это похоже.)