2016-03-30 29 views
2

şu örneği düşünelim:polimorfizm aynı türde bir nesne oluşturmak

class InheritedType extends Type { 

    public Type simplify() { 
     Type newLeft = left.simplify(); 
     Type newRight = right.simplify(); 
     Type newExpr = new InheritedType(newLeft, newRight); 
     return newExpr.simplify(); 
    } 
} 

Şimdi başka kalıtsal tip

class InheritedType2 extends Type { 

    public Type simplify() { 
     Type newLeft = left.simplify(); 
     Type newRight = right.simplify(); 
     Type newExpr = new InheritedType2(newLeft, newRight); 
     return newExpr.simplify(); 
    } 
} 

oluşturmak istiyorum Bu yöntem sadece aynı, sadece yapıcı adıdır farklıdır. Kod çoğaltmasını önlemek için herhangi bir yolu var mı? Aşağıdaki kod çalışmaz

class Type { 

    public Type simplify() { 
     Type newLeft = left.simplify(); 
     Type newRight = right.simplify(); 
     Type newExpr = new this(newLeft, newRight); 
     return newExpr.simplify(); 
    } 
} 
+0

Kodunuz gerçekten mantıklı değil var. 'Sadeleştirme' için yapılan her çağrı, 'sadeleştirmek' için bir özyinelemeli çağrıyla sona erer. Yöntemleriniz, bildirilmemiş alanlara başvuruda bulunur, dolayısıyla bildirilmelerini istediğiniz yerleri netleştirmezsiniz. Yararlı tavsiyeler almak için en az * doğru * örnek göndermelisiniz. – ruakh

cevap

4

Bu soruna tipik yolu InheritedType ve InheritedType2 için ortak üst sınıf tanıtmaktır. Bunun nedeni, açıkça, bu iki türün mantığı paylaşmasıdır: temel olarak hem sol hem de sağ işlenenler üzerinde çalışırlar.

abstract class LeftRightType extends Type { 

    private Type left, right; 

    public LeftRightType(Type left, Type right) { 
     this.left = left; 
     this.right = right; 
    } 

    @Override 
    public Type simplify() { 
     return newInstance(left.simplify(), right.simplify()).simplify(); 
    } 

    public abstract Type newInstance(Type left, Type right); 

} 

Bu, o anda çoğaltma olan mantığı tutan ve uygulayıcılarının geçersiz kılar bir newInstance soyut yöntem haline somut örneğinin oluşturulmasını temsilci: Yani bize LeftRightType (daha iyi bir isim olmadığı için) oluşturalım. Sonra sadece Java'yı 8 kullanıyorsanız, somut sınıfı vererek çok yapıcı doğrudan dönmek olduğunu yoğunlaşabilir ki

class InheritedType extends LeftRightType { 
    public InheritedType(Type left, Type right) { 
     super(left, right); 
    } 
    @Override 
    public Type newInstance(Type left, Type right) { 
     return new InheritedType(left, right); 
    } 
} 

class InheritedType2 extends LeftRightType { 
    public InheritedType2(Type left, Type right) { 
     super(left, right); 
    } 
    @Override 
    public Type newInstance(Type left, Type right) { 
     return new InheritedType2(left, right); 
    } 
} 

Not olabilir. Artık soyut bir yönteme bile gerek yok.

abstract class LeftRightType extends Type { 

    private Type left, right; 
    private BinaryOperator<Type> typeSupplier; 

    public LeftRightType(Type left, Type right, BinaryOperator<Type> typeSupplier) { 
     this.left = left; 
     this.right = right; 
     this.typeSupplier = typeSupplier; 
    } 

    public Type simplify() { 
     return typeSupplier.apply(left.simplify(), right.simplify()).simplify(); 
    } 
} 

ve sonra

class InheritedType extends LeftRightType { 
    public InheritedType(Type left, Type right) { 
     super(left, right, InheritedType::new); 
    } 
} 

class InheritedType2 extends LeftRightType { 
    public InheritedType2(Type left, Type right) { 
     super(left, right, InheritedType2::new); 
    } 
} 
2

erişebilmek için "merakla yinelenen şablon desen" https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern:

abstract class Type<This extends Type<This>> { 
    protected abstract This newInstance(Type<?> newLeft, Type<?> newRight); 

    public This simplify() { 
     Type<?> newLeft = left.simplify(); 
     Type<?> newRight = right.simplify(); 
     This newExpr = newInstance(newLeft, newRight); 
     return newExpr.simplify(); 
    } 
} 

class InheritedType extends Type<InheritedType> { 
    protected InheritedType newInstance(Type<?> left, Type<?> right) { 
     new InheritedType(left, right); 
    } 
} 

class InheritedType2 extends Type<InheritedType2> { 
    protected InheritedType2 newInstance(Type<?> left, Type<?> right) { 
     new InheritedType2(left, right); 
    } 
} 
İlgili konular