Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala equivalent of python __getattr__ / __setattr__

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

like image 732
ts. Avatar asked Dec 12 '22 02:12

ts.


2 Answers

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

like image 163
Debilski Avatar answered Dec 24 '22 21:12

Debilski


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).

like image 43
Daniel C. Sobral Avatar answered Dec 24 '22 21:12

Daniel C. Sobral