Quando usar encadeamento
O encadeamento de funções é popular principalmente em idiomas em que um IDE com preenchimento automático é um local comum. Por exemplo, quase todos os desenvolvedores de C # usam o Visual Studio. Portanto, se você estiver desenvolvendo com C #, adicionar encadeamento a seus métodos pode economizar tempo para os usuários dessa classe, pois o Visual Studio o ajudará na criação da cadeia.
Por outro lado, linguagens como PHP, que são altamente dinâmicas por natureza e geralmente não têm suporte de preenchimento automático em IDEs, terão menos classes que suportam encadeamento. O encadeamento somente será apropriado quando phpDocs corretos forem empregados para expor os métodos encadeados.
O que é encadeamento?
Dada uma classe denominada, Foo
os dois métodos a seguir são encadeados.
function what() { return this; }
function when() { return new Foo(this); }
O fato de ser uma referência à instância atual e criar uma nova instância não altera que esses sejam métodos encadeados.
Não há regra de ouro de que um método encadeado possa fazer referência apenas ao objeto atual. Os métodos encadeados e de fato podem ser divididos em duas classes diferentes. Por exemplo;
class B { function When() { return true; } };
class A { function What() { return new B(); } };
var a = new A();
var x = a.What().When();
Não há referência a this
nenhum dos exemplos acima. O código a.What().When()
é um exemplo de encadeamento. O interessante é que o tipo de classe B
nunca é atribuído a uma variável.
Um método é encadeado quando seu valor de retorno é usado como o próximo componente de uma expressão.
Aqui estão mais alguns exemplos
// return value never assigned.
myFile.Open("something.txt").Write("stuff").Close();
// two chains used in expression
int x = a.X().Y() * b.X().Y();
// a chain that creates new strings
string name = str.Substring(1,10).Trim().ToUpperCase();
Quando usar this
enew(this)
As strings na maioria dos idiomas são imutáveis. Portanto, as chamadas de método de encadeamento sempre resultam na criação de novas strings. Onde como um objeto como StringBuilder pode ser modificado.
Consistência é a melhor prática.
Se você possui métodos que modificam o estado de um objeto e retornam this
, não misture métodos que retornam novas instâncias. Em vez disso, crie um método específico chamado Clone()
que fará isso explicitamente.
var x = a.Foo().Boo().Clone().Foo();
Isso é muito mais claro quanto ao que está acontecendo lá dentro a
.
A etapa fora e truque traseiro
Eu chamo isso de truque passo a passo , porque resolve muitos problemas comuns relacionados ao encadeamento. Basicamente, significa que você sai da classe original para uma nova classe temporária e depois volta para a classe original.
A classe temporária existe apenas para fornecer recursos especiais à classe original, mas somente sob condições especiais.
Muitas vezes, uma cadeia precisa mudar de estado , mas a classe A
não pode representar todos esses estados possíveis . Portanto, durante uma cadeia, é introduzida uma nova classe que contém uma referência para A
. Isso permite que o programador entre em um estado e volte para A
.
Aqui está o meu exemplo, que o estado especial seja conhecido como B
.
class A {
function Foo() { return this; }
function Boo() { return this; }
function Change() return new B(this); }
}
class B {
var _a;
function (A) { _a = A; }
function What() { return this; }
function When() { return this; }
function End() { return _a; }
}
var a = new A();
a.Foo().Change().What().When().End().Boo();
Agora esse é um exemplo muito simples. Se você quiser ter mais controle, B
poderá retornar a um novo supertipo A
que possui métodos diferentes.