4

Is there scala equivalent of python __getattr__ / __setattr__ (and other __*__ methods?). Some thing built-in or maybe some traits?

ts.
  • 10,510
  • 7
  • 47
  • 73

2 Answers2

11

For __getattr__ and __setattr__ you’ll have to wait until someone with more insight describes the new Scala 2.10 reflection API. (And of course: it won’t be directly translatable ever. It depends completely on your use case. If you just want a dynamic class, there will be a Dynamic trait in the future; if you just want a tiny bit of that, then designing around pattern matching may be an obvious choice.)

As for the multitude of other __*__ methods in Python:

Global things

  • __call__apply() // pretty much identical in behaviour
  • __metaclass__ // use case dependent:
    • currently class inheritance or trait mixins may be useful
    • in many cases all that metaclass does is instance construction which avoids a call to super(); in Scala super() is always called in the constructor.
  • __repr__, __str__toString()
  • __eq__equals()
  • __init__ // implicitly called in the class body
  • __new__ // not directly existent; depending on use case early initialisation
  • __del__ // missing
  • __nonzero__ // not really, except implicit def toBool[MyType](a: MyType): Boolean = ...

Container Types

  • __len__length, size or whatever is the convention in the container
  • __getitem__apply(i: IndexType) // containers are functions in Scala
  • __setitem__update(i: IndexType, v: ValueType)
  • __delitem__ // no special handling needed; container convention
  • __iter__foreach(block: ValueType => Unit) // with return value: map, flatMap

Notably, apply and update are special in Scala, just as their Python counterparts. They allow for the following Syntax:

val x = collection(elem) // val x = collection.apply(elem)
collection(elem) = y // collection.update(elem, y)

Similarly, just as Python’s __iter__ allows a syntax like (el for el in container) foreach and map make it possible to say for (el <- container) yield el.

Operators

generally no special handling needed as we are allowed to define those directly:

  • __add__, __sub__, … // just define def + (arg: T) or def - (arg: T)

this also includes comparison operators

  • __lt__, __ge__def <(other: T), def <=(other: T)

however, just as in Python, there are some special cases in the compiler for advanced things:

  • __radd__, __rsub__, … // right-associative operators; approx. def +: (arg: T) or def -: (arg: T) (append a :)
  • __iadd__, __isub__, … // modifying operators: def += (arg: T), …

Context manager

  • __enter__, __exit__ // in most cases, a function argument fulfills the same purpose

See also: List of Scala's "magic" functions

Community
  • 1
  • 1
Debilski
  • 66,976
  • 12
  • 110
  • 133
  • (Is there something wrong apart from the fact that `__getattr__` and `__setattr__` are prominently missing?) – Debilski May 19 '12 at 01:01
2

I'm not sure what's the point here. Scala's uniform access principle means "fields" and methods share the same interface -- because, in fact, "fields" in Scala are getters and setters.

In other words, you can replace them like this:

var x: Int = 0

private[this] var _x = 0
def x = _x
def x_=(n: Int) { _x = n }

The getter and setter methods will control access to the private field you declared.

Now, if all you want is a way to provide non-static fields, you have to look at the Dynamic trait. It's experimental up to 2.9.2, but it will be available on 2.10, though behind a flag to warn people that this feature is dangerous (because it introduces dynamic typing, but if you don't think dynamic typing is dangerous, you should be fine).

Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • `__getattr__` and `__setattr__` are not directly related to the uniform access principle in Python (at least not since the `property` decorator has been established). – Debilski May 19 '12 at 00:09