Giriş
Curiously recurring template pattern kullanımının iki tane ana konusu var.
1. Polymorphism . Örneğin Template Method Pattern için kullanılabilir.
2. Ata sınıfta kalıtan sınıf tipine olan ihtiyaç. Örneğin Binary Tree, Fluent Methods gibi kullanım çeşitlerinde gerek olabilir.
Data Structures kullanımında ata sınıf T tipinden bir başka child veya parent nesneye erişim ister. Örneğin Binary Tree, Linked List gibi veri yapılarında bu durum vardır.Eğer CRTP kullanmazsak kod şöyle olur.
Builder Pattern
Elimizde şöyle bir kod olsun.
Örnek
Şöyle yaparız. Burada hem arayüzün gerektirdiği copy() metodu tanımlanıyor hem de bu metodun kalıtan T tipinden döneceği belirtiliyor
Kendisinden yeni nesne yaratan kod için şöyle yaparız.
Curiously recurring template pattern kullanımının iki tane ana konusu var.
1. Polymorphism . Örneğin Template Method Pattern için kullanılabilir.
2. Ata sınıfta kalıtan sınıf tipine olan ihtiyaç. Örneğin Binary Tree, Fluent Methods gibi kullanım çeşitlerinde gerek olabilir.
Data Structures kullanımında ata sınıf T tipinden bir başka child veya parent nesneye erişim ister. Örneğin Binary Tree, Linked List gibi veri yapılarında bu durum vardır.Eğer CRTP kullanmazsak kod şöyle olur.
public class Node {
private Node parent;
private List<Node> children;
}
Fluent Methods kullanımında ata sınıf metodu T tipi dönecek şekilde yazılır. Böylece kalıtan sınıf otomatik olarak kendini döner. Cast etmeye gerek kalmaz.Builder Pattern
Elimizde şöyle bir kod olsun.
class A {
private final int value;
public static <T extends Builder<T>> T builder() {
return (T)new Builder<>();
}
protected A(Builder<? extends Builder<?>> builder) {
value = builder.value;
}
public static class Builder<T extends Builder<T>> {
private int value;
public T withValue(int value) {
this.value = value;
return (T)this;
}
public A build() {
return new A(this);
}
}
}
Şöyle bir kod olsun.class B extends A {
private final String name;
public static <T extends Builder<T>> T builder() {
return (T)new Builder<>();
}
protected B(Builder<? extends Builder<?>> builder) {
super(builder);
name = builder.name;
}
public static class Builder<T extends Builder<T>> extends A.Builder<T> {
private String name;
public Builder<T> withName(String name) {
this.name = name;
return this;
}
public B build() {
return new B(this);
}
}
}
Şöyle yaparız.A a = A.builder().withValue(1).build();
B b = B.builder().withValue(2).withName("xx").build();
Template PatternÖrnek
Şöyle yaparız. Burada hem arayüzün gerektirdiği copy() metodu tanımlanıyor hem de bu metodun kalıtan T tipinden döneceği belirtiliyor
public interface Recur<T extends Recur<T>> {
T copy();
}
Kalıtan sınıf için şöyle yaparız.class A implements Recur<A> {
@Override
public A copy() {
return new A();
}
}
Şu kod derlenmez çünkü T tipinin Recur sınıfından kalıtması gerekir.class A implements Recur<String> {...}
ÖrnekKendisinden yeni nesne yaratan kod için şöyle yaparız.
public class Sample<T extends Sample<T>> {
public static Sample<? extends Sample<?>> get() {
final Sample<?> s = get0();
return s;
}
private static <T extends Sample<T>> Sample<T> get0() {
return new Sample<T>();
}
}
get metodu şöyle de olabilirdipublic static <X extends Sample<X>> Sample<? extends Sample<?>> get() {
return new Sample<X>();
}
Örnek
Kalıtan sınıfın kendi tipinden bir abstract metodu yapmasını isteyelim. Elimizde şöyle bir kod olsun.
Kalıtan sınıfın kendi tipinden bir abstract metodu yapmasını isteyelim. Elimizde şöyle bir kod olsun.
abstract class Event<T extends Event<T>> {
abstract boolean intersect(T object);
}
Şöyle yaparızclass SubClassEvent extends Event<SubClassEvent> {
@Override
boolean intersect(SubClassEvent object){return true;}
}
Hiç yorum yok:
Yorum Gönder