[SCALA] 어떻게 혼합 된합니다 인스턴스에 대한 특성?
SCALA어떻게 혼합 된합니다 인스턴스에 대한 특성?
을 감안할 때 우려 MyTrait :
trait MyTrait {
def doSomething = println("boo")
}
확장하거나와 함께 클래스에 혼합 할 수 있습니다 :
class MyClass extends MyTrait
또한 새로운 인스턴스를 인스턴스화에 혼합 할 수 있습니다 :
var o = new MyOtherClass with MyTrait
o.doSomething
하지만 ... 수있는 특성 (또는 그 차이가 취하면 다른) 기존 인스턴스에 추가?
나는 자바에서 JPA를 사용하여로드 객체를 그리고 난 특성을 사용하여 몇 가지 기능을 추가하고 싶습니다. 그것은 전혀 할 수 있습니까?
나는 다음과 같은 특성에 혼합 할 수 있도록하고 싶습니다 :
var o = DBHelper.loadMyEntityFromDB(primaryKey);
o = o with MyTrait //adding trait here, rather than during construction
o.doSomething
해결법
-
==============================
1.나는이 사용에 대한 아이디어를 가지고 :
나는이 사용에 대한 아이디어를 가지고 :
//if I had a class like this final class Test { def f = println("foo") } trait MyTrait { def doSomething = { println("boo") } } object MyTrait { implicit def innerObj(o:MixTest) = o.obj def ::(o:Test) = new MixTest(o) final class MixTest private[MyTrait](val obj:Test) extends MyTrait }
아래로이 특성을 사용할 수 있습니다 :
import MyTrait._ val a = new Test val b = a :: MyTrait b.doSomething b.f
귀하의 예제 코드 :
val o = DBHelper.loadMyEntityFromDB(primaryKey) :: MyTrait o.doSomething
내가 당신을 도울 수 있기를 바랍니다.
업데이트]
object AnyTrait { implicit def innerObj[T](o: MixTest[T]):T = o.obj def ::[T](o: T) = new MixTest(o) final class MixTest[T] private[AnyTrait](val obj: T) extends MyTrait }
그러나이 패턴은 이미 정의 된 몇 가지 암시 도우미 방법을 사용할 수 없습니다, 일부는 제한이있다.
val a = new Test a.f val b = a :: AnyTrait b.f1 b.f val c = "say hello to %s" :: AnyTrait println(c.intern) // you can invoke String's method println(c.format("MyTrait")) //WRONG. you can't invoke StringLike's method, though there defined a implicit method in Predef can transform String to StringLike, but implicit restrict one level transform, you can't transform MixTest to String then to StringLike. c.f1 val d = 1 :: AnyTrait println(d.toLong) d.toHexString // WRONG, the same as above d.f1
-
==============================
2.JVM의 기존 런타임 객체는 힙에 특정 크기를 갖는다. 그것에 특성을 추가하면 힙 크기를 변경, 그 서명을 변경하는 것을 의미한다.
JVM의 기존 런타임 객체는 힙에 특정 크기를 갖는다. 그것에 특성을 추가하면 힙 크기를 변경, 그 서명을 변경하는 것을 의미한다.
갈 수있는 유일한 방법은 컴파일 타임에 변화의 어떤 종류의 일을하는 것입니다 그래서.
스칼라의 믹스 인 구성은 컴파일시에 발생합니다. 어떤 컴파일러 수 잠재적 할 기존 객체 A를 단순히 전달 모든 호출 한 다음 B.이에 형질 T 믹스는하지만, 구현되지 않은 것과 같은 유형의 기존 개체 A를 주위에 래퍼 B를 만드는 것입니다. 객체 A는 확장 할 수 없습니다 최종 클래스의 인스턴스가 될 수 있기 때문에이 가능할 것이다 때 의문이다.
요약하면, 믹스 인 구성은 기존 개체의 인스턴스 수 없습니다.
업데이트 :
어떤 특성을 가진 스마트 구골 산에 의해 제안 된 솔루션 및 작업에 일반화 관련, 이것은 지금까지 내가 가진 같습니다. 아이디어는 DynamicMixinCompanion의 특성에 공통의 믹스 인 기능을 추출하는 것입니다. 클라이언트는 자신이에 대한 동적 믹스 인 기능을 가지고 싶어 각 특성에 대한 동반자 객체 확장 DynamicMixinCompanion을 만들어야합니다. 이 동반자 객체는 익명의 특성 개체 (작성되는 정의가 필요합니다 : :).
trait DynamicMixinCompanion[TT] { implicit def baseObject[OT](o: Mixin[OT]): OT = o.obj def ::[OT](o: OT): Mixin[OT] with TT class Mixin[OT] protected[DynamicMixinCompanion](val obj: OT) } trait OtherTrait { def traitOperation = println("any trait") } object OtherTrait extends DynamicMixinCompanion[OtherTrait] { def ::[T](o: T) = new Mixin(o) with OtherTrait } object Main { def main(args: Array[String]) { val a = "some string" val m = a :: OtherTrait m.traitOperation println(m.length) } }
-
==============================
3.나는 보통 기존 객체에 새로운 방법으로 혼합하는 암시를 사용했다.
나는 보통 기존 객체에 새로운 방법으로 혼합하는 암시를 사용했다.
나는 다음과 같이 몇 가지 코드가있는 경우, 참조 :
final class Test { def f = "Just a Test" ...some other method } trait MyTrait { def doSomething = { println("boo") } } object HelperObject { implicit def innerObj(o:MixTest) = o.obj def mixWith(o:Test) = new MixTest(o) final class MixTest private[HelperObject](obj:Test) extends MyTrait }
그리고 당신은 이미 존재하는 객체 테스트와 MyTrait 방법을 사용할 수 있습니다.
val a = new Test import HelperObject._ val b = HelperObject.mixWith(a) println(b.f) b.doSomething
귀하의 예를 들어, 당신은 다음과 같이 사용할 수 있습니다 :
import HelperObject._ val o = mixWith(DBHelper.loadMyEntityFromDB(primaryKey)); o.doSomething
나는이 HelperObject을 정의하기 위해 지사 구문을 생각하고있다 :
trait MyTrait { ..some method } object MyTrait { implicit def innerObj(o:MixTest) = o.obj def ::(o:Test) = new MixTest(o) final class MixTest private[MyTrait](obj:Test) extends MyTrait } //then you can use it val a = new Test val b = a :: MyTrait b.doSomething b.f // for your example val o = DBHelper.loadMyEntityFromDB(primaryKey) :: MyTrait o.doSomething
-
==============================
4.어떤 암시 클래스에 대한? 그것은 최종 내부 클래스와 "믹스 인"α- 함수와 다른 답변의 방법에 비해 나에게 쉽게 보인다.
어떤 암시 클래스에 대한? 그것은 최종 내부 클래스와 "믹스 인"α- 함수와 다른 답변의 방법에 비해 나에게 쉽게 보인다.
trait MyTrait { def traitFunction = println("trait function executed") } class MyClass { /** * This inner class must be in scope wherever an instance of MyClass * should be used as an instance of MyTrait. Depending on where you place * and use the implicit class you must import it into scope with * "import mypackacke.MyImplictClassLocation" or * "import mypackage.MyImplicitClassLocation._" or no import at all if * the implicit class is already in scope. * * Depending on the visibility and location of use this implicit class an * be placed inside the trait to mixin, inside the instances class, * inside the instances class' companion object or somewhere where you * use or call the class' instance with as the trait. Probably the * implicit class can even reside inside a package object. It also can be * declared private to reduce visibility. It all depends on the structure * of your API. */ implicit class MyImplicitClass(instance: MyClass) extends MyTrait /** * Usage */ new MyClass().traitFunction }
-
==============================
5.왜 스칼라의 내 라이브러리 패턴을 확장 사용하지?
왜 스칼라의 내 라이브러리 패턴을 확장 사용하지?
https://alvinalexander.com/scala/scala-2.10-implicit-class-example
나는 반환 값의 무엇인지 확실하지 않다 :
var에 O = DB (기본 키)에서 DBHelper.load 내 엔티티;
그러나 우리의 예를 들어 DBEntity입니다, 우리가 가정 해 봅시다. 당신은 클래스 DBEntity을 그리고 그것은 당신의 특성, MyTrait를 확장하는 클래스로 변환 할 수 있습니다.
뭔가 같은 :
trait MyTrait { def doSomething = { println("boo") } } class MyClass() extends MyTrait // Have an implicit conversion to MyClass implicit def dbEntityToMyClass(in: DBEntity): MyClass = new MyClass()
난 당신이 또한 단지 암시 클래스를 사용하여이 작업을 단순화 할 수 있으리라 생각합니다.
implicit class ConvertDBEntity(in: DBEntity) extends MyTrait
이 혼합 된 수있는 특성 :: 연산자를 오버로드 c를 나는 특히 / 여기에 B를 허용 대답을 싫어한다.
스칼라에서는 :: 연산자 즉 시퀀스에 사용됩니다 :
val x = 1 :: 2 :: 3 :: Nil
조금 어색한 상속 느낌 IMHO의 수단으로 사용.
from https://stackoverflow.com/questions/3893274/how-to-mix-in-a-trait-to-instance by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 왜 기능은 [-A1, ..., + B]되지 매개 변수와 같은 슈퍼 타입을 허용 어떻습니까? (0) | 2019.11.19 |
---|---|
[SCALA] "[삼백초] 후 시간 초과 선물 java.util.concurrent.TimeoutException"왜 실패에 가입합니까? (0) | 2019.11.19 |
[SCALA] reduceByKey : 어떻게 내부적으로 작동합니까? (0) | 2019.11.19 |
[SCALA] 스파크 - 응용 프로그램을 제출할 때 오류 "A 마스터 URL이 구성에서 설정해야합니다" (0) | 2019.11.19 |
[SCALA] 어떻게 스칼라에서 I 설정 여러 유형의 경계는 무엇입니까? (0) | 2019.11.19 |