0

I want to define case class demo(notify: String), but my IDE (IntelliJ IDEA) complains that "notify cannot override final member".

I know that notify is a member method of AnyRef and the IDE may confuse variable name for method name. I need a notify field, how can I do that?

Ben Reich
  • 16,222
  • 2
  • 38
  • 59
vincent chou
  • 91
  • 2
  • 8
  • Why can't you just call it something different? `_notify` would work. – timleathart Apr 21 '15 at 02:31
  • I'm using jackson to map from case class to json, since the structure of json cannot be changed(other service would consume the json data), I have to use `notify` field in my case class. – vincent chou Apr 21 '15 at 05:26
  • That question: http://stackoverflow.com/q/7893619/1296806 – som-snytt Apr 21 '15 at 07:54
  • 1
    You can use [jackson-annotations](https://github.com/FasterXML/jackson-annotations) to customize the mapping, so that you are not required to have a value with the exact same name as in the JSON. It would become something like `case class demo(@JsonProperty("notify") notify_: String)` – Jesper Apr 21 '15 at 07:57
  • Did you follow the other link? Then close as duplicate. – som-snytt Apr 21 '15 at 14:45

2 Answers2

6

This isn't a problem with the IDE. A Scala class can't have conflicting symbols, whether or not they are methods or fields. For example, the following won't compile:

class Foo {
    val bar = 1
    def bar() = "bar"
}

notify is defined on AnyRef, and furthermore it is final, so you don't really have any great options here!

You can name the variable something different, of course:

case class Foo(_notify: String)

If you insist on the variable name, you can also extends AnyVal, but only if you have exactly one val parameter:

case class Foo(notify: String) extends AnyVal

You might be looking for the feature that allows you to escape keywords with the grave accent:

case class Foo(`val`: String)

This would allow you to use a keyword (and some other normally illegal variable names) as a variable name. This doesn't apply to your example, since notify isn't a keyword – it's an already used symbol on the class!

You can also come up with a solution where notify is private to the class, but that won't work with case classes or most reasonable use cases.

Ben Reich
  • 16,222
  • 2
  • 38
  • 59
  • `case class Foo(notify: String) extends AnyVal` won't work either. I'm expecting something like using keyword as variable name, simply by adding 'keyword' – vincent chou Apr 21 '15 at 05:32
  • @vincentchou I've added an edit that explains how to escape keywords. Also what do you mean `AnyVal` won't work? – Ben Reich Apr 21 '15 at 11:02
  • Thanks for answering, but @Jesper have already solved my problem. I thought scala would provide some kind of mechanism to allow us use `notify` or `toString` as variable name, but it didn't. @Jesper provided another trait of thought by taking advantage of jackson annotation, which is very handy in dealing with this problem. – vincent chou Apr 21 '15 at 11:56
  • @vincentchou Ok – you should answer your own question then, and mark this as resolved! And next time, make sure to ask your question in context so that a reader can better help resolve the issue. A classic version of the XY problem – you were asking how to name a variable `notify`, but what you really wanted was a way to serialize an object in a certain way! http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – Ben Reich Apr 21 '15 at 14:15
1

Ignoring your use case, a field called notify:

scala> class X(private[this] val notify: Int) { def f = notify * 2 }
defined class X

scala> new X(5).f
res1: Int = 10

scala> :javap -prv X
Binary file X contains $line6.$read$$iw$$iw$X
[snip]
{
  private final int notify;
    flags: ACC_PRIVATE, ACC_FINAL

  public int f();
    flags: ACC_PUBLIC
[snip]
som-snytt
  • 39,429
  • 2
  • 47
  • 129