2016-04-08 46 views
0

Ben aynı kodlama desenli birkaç işlevi vardır: kodum az, benFonksiyon

private def updateDomainObjectValidationStatus(f1: Long => Option[DomainObject], 
       parameter1: Long, 
       f2: DomainObject => Option[DomainObject], 
       paramter2: String, 
       valid: Boolean): Option[DomainObject] ={ 

    val somethingMaybe = f1(parameter1) 
    somethingMaybe match { 
    case Some(something) => 
     f2(
     something.copyMe(updatedBy = Some(paramter2), 
     validationStatus = if(valid) Some(DataEntryValidationStatus.Valid) else Some(DataEntryValidationStatus.Invalid)) 
    ) 
    case None => 
     throw new DomainException(s"Object with ID: '$parameter1' doesn't exist") 
    } 
} 

olarak yeni bir özel fonksiyon yazmak tekrarlanan yapmak için

def updateFooValidationStatus(fooId: Long, user: String, valid: Boolean): Option[Foo] = { 

    val fooMaybe = fooDao.getFooById(activityId) 
    fooMaybe match { 
    case Some(foo) => { 
     fooDao.update(foo.copy(updatedBy = Some(user), 
     validationStatus = if (valid) Some(DataEntryValidationStatus.Valid) else Some(DataEntryValidationStatus.Invalid)) 
    ) 
    } 
    case None => 
    throw new DomainException(s"Foo with ID: '$fooId' doesn't exist") 
    } 
} 

trait DomainObject { ... } 

case class Foo(...) extends DomainObject { ... } 

Yukarıdaki değişikliklerle, ancak, bir güncelleştirme nedeniyle updateFaviValidationStatus içinde updateDomainObjectValidationStatus'u arayamıyorum

type mismatch, expected (DomainObject) => Option[DomainObject], actual (Foo) => Option[Foo] 

İlginçtir bir parametreye n hata, bu

(Long) => Option[Foo] 

Ne için bir kod deyimsel Scala tasarım moda olacak sürer ilk parametreyi

(Long) => Option[DomainObject] 

şikayet etmiyor Yukarıdaki kod çalışır?

+0

'' '' '' '' '' işlevler değil, bunlar – pedrofurla

cevap

4

burada olur Nedir: işlevleri onların argüman türü (ler) ve bunların dönüş türü yılında kovaryant yılında kontravaryant çünkü updateDomainObjectValidationStatus, tip (DomainObject) => Option[DomainObject] bir argüman olarak tip (Foo) => Option[Foo] birlikte bir değer kabul edemez. Bu ne anlama geliyor? AB uzanır

  • sonraA döndüren bir işlev B dönen bir işlev uzanır
  • Ancak A, ile daha sonra bir işlev B sürdüğü taktirde her (derleyici ilk parametresi hakkında şikayet etmiyor bu yüzden) B türündeki argümanı, A türünde bir argümanı genişletir;

Bu neden anlamlı?

Bunu bir düşünün: A extends B ise "A is a B" diyebiliriz. Şimdi, "A'da bir işlev" A üzerinde çalışabilir, ancak herhangi bir B üzerinde değil, değil mi? Eğer işlevin bir Int argümanı varsa, AnyVal tipiyle bir değer iletemezsiniz ... Tersi işe yarar - AnyVal'da bir fonksiyon kesinlikle Int ile çağrılabilir.

Bunu düzeltmek için - en iyi yaklaşım updateDomainObjectValidationStatus bir DomainObject uzanır tip vermek olacak gibi bu durumda, görünür: türe (Long) => Option[Foo] bir ilk parametre ile çağırdığınızda

private def updateDomainObjectValidationStatus[T <: DomainObject](
    f1: Long => Option[T], 
    parameter1: Long, 
    f2: T => Option[T], 
    paramter2: String, 
    valid: Boolean): Option[T] = { ... } 

, T türünün Foo olduğu anlaşılır ve derleyici beklendiği gibi üçüncü için (Foo) => Option[Foo] olmasını bekler.Hatta iyi bir bonus elde edersiniz - dönüş tipi daha spesifik olacaktır: Option[DomainObject] yerine Option[Foo].

+0

yöntemidir. Ayrıntılı açıklama için çok teşekkür ederiz. Değişim için, DomainObject özelliğinin yanı sıra alt vaka sınıflarını da parametrelendirmem gerekiyor. Özellikte tanımlanan bir yöntem imzası vardır. Oldukça az sayıda düzeltmeden sonra çalışmam gerek. – TeeKai