1

Depending upon what type of object I pass in X, I need to use the apply methods.I can specify the modifier I want to use(Y or Z). I need to have a syntax of using the 'following' function like this:

(object of type B) following Y

or

(object of type C) following Z

The code looks like this:

trait A 
{
    def following(modifier: X) = modifier(this)
}
case class B() extends A{}
case class C() extends A{}
trait X {}
object Y extends X
{
    apply(obj: B):B = {}
    apply(obj: C):C = {}
}
object Z extends X
{
    apply(obj: B):B = {}
    apply(obj: C):C = {}
}

The compiler gives error in the line where I have implemented the 'following' function. What am I doing wrong?

3
  • 1
    What are you expecting as the outcome of this function, and what error are you getting? Commented Oct 30, 2013 at 12:17
  • For example: I need to change one field of the object of class B. so, modifier Y takes an object of type B, changes one of its fields (I have skipped its logic) and returns an object of same type but with one of the fields changed. Commented Oct 30, 2013 at 12:19
  • 1
    I recommend adding that info to the question (Eg. show expected use and outcome), along with the actual error you are getting. Commented Oct 30, 2013 at 12:40

2 Answers 2

3

I guess what you want is something like that:

    trait X {
        def apply[T](obj: T): T
    }

    trait A {
        def following(modifier: X) = modifier(this)
    }

    case class B() extends A
    case class C() extends A

    object Y extends X {
        override def apply[B](obj: B): B = { obj }
        override def apply[C](obj: C): C = { obj }
    }

    object Z extends X {
        override def apply[B](obj: B): B = { obj }
        override def apply[C](obj: C): C = { obj }
    }

Unlucky I don't think you can have two overrided apply methods and because of that it won't compile. If this is possible, then I will be happy to know as well. What you can do for now is to use one apply method with pattern matching:

    trait X {
        def apply[T](obj: T): T
    }

    trait A {
        def following(modifier: X) = modifier(this)
    }

    case class B() extends A
    case class C() extends A

    object Y extends X {
        override def apply[T](obj: T): T = {
            obj match {
                case o: B => obj
                case o: C => obj
            }
        }
    }

    object Z extends X {
        override def apply[T](obj: T): T = {
            obj match {
                case o: B => obj
                case o: C => obj
            }
        }
    }

You could also get exactly the same effect (including syntax) doing it other way around. In my opinion is much cleaner and easier to understand:

    sealed trait X
    case class Y() extends X
    case class Z() extends X

    trait A[T] {
        def following(modifier: X): T
    }

    case class B() extends A[B] {
        override def following(modifier: X) = modifier match {
            case o: Y => this
            case o: Z => this
        }
    }

    case class C() extends A[C] {
        override def following(modifier: X) = modifier match {
            case o: Y => this
            case o: Z => this
        }
    }
Sign up to request clarification or add additional context in comments.

Comments

1

There are several things you are doing wrong:

  1. your apply defintions in Y and Z need to be have def.
  2. trait X needs to have the apply methods defined, though only as abstract methods.
  3. following needs to be overriden in B and C, so that the compiler will know which overloaded method in X to invoke.
  4. following needs to be abstract in A.

You are implementing the Visitor pattern. I suggest finding a copy of the gang of four book, and work from the examples in there.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.