How classes in these codes work (Python)? - class

<Code 1>
class A:
def __init__(self, a):
self.__a=a
a=A(5)
a.b=10
print(a.b) #10
<Code 2>
class A:
def __init__(self, a):
self.__a=a
a=A(5)
a.__a=10
print(a.__a) #10
a.__a+=5
print(a.__a) #15
If there are no variable in class, does setter makes variable in class?
Eventhough variable is private?

Related

Is new instance of class created per each implicit class conversion?

object test extends App {
implicit class f(i: Int) { println("!!!"); def f = 42 + i }
1.f
2.f
3.f
}
In .class file we see
public static test$f f(int);
Code:
0: getstatic #16 // Field test$.MODULE$:Ltest$;
3: iload_0
4: invokevirtual #42 // Method test$.f:(I)Ltest$f;
7: areturn
So, looks like there is a static method, but this code prints "!!!" 3 times when run. Do we have new class instantiation per each implicit class conversion? If yes, why? If no, why "!!!" was print thrice?
You can avoid instantiating your extension class by making it a value class
implicit class f(val i: Int) extends AnyVal { def f = 42 + i }
Note, that then you can't put println inside, but here's a quote from the docs linked above:
At runtime, this expression 3.toHexString is optimised to the equivalent of a method call on a static object (RichInt$.MODULE$.extension$toHexString(3)), rather than a method call on a newly instantiated object.
Yes - implicit Class is shorthand for the creation a class and implicit def for creating an instance i.e. in your example:
object test extends App {
class f(i: Int) { println("!!!"); def f=42+i}
implicit def toF(i : int) = new f(i)
}

Implementation of toString() for Tuples/Product/case classes

I want to customize a case class toString() method.
case class MyCaseClass {
// stuff ..
override def toString() {
// mostly same as default but I want to omit some of the fields
}
My first look was into the Product and Product extended by all case classes . But turns out they are traits that do not contain the toString() .
So where in the scala library class hierarchy for case classes (/Products) is the toString() located?
toString is automatically generated by the scala compiler. The only thing you can customize is the productPrefix
Here is a simple case class
case class Foo(a: Int, b: Int)
And its toString method (using :javap -c Foo in the scala console)
public java.lang.String toString();
Code:
0: getstatic #63 // Field scala/runtime/ScalaRunTime$.MODULE$:Lscala/runtime/ScalaRunTime$;
3: aload_0
4: invokevirtual #85 // Method scala/runtime/ScalaRunTime$._toString:(Lscala/Product;)Ljava/lang/String;
7: areturn
So as you can see, toString is implemented by calling scala.runtime.ScalaRunTime._toString(this).
If you just want to change the name of your class, you can override productPrefix:
case class FooImpl(a: Int, b: Int) {
override def productPrefix = "Foo"
}
scala> FooImpl(1,2)
res1: FooImpl = Foo(1,2)
If you want to do something more complex, like omitting some fields, you will have to just override toString
case class Foo3(a: Int, b: Int, c: Int) {
override def toString = "Foo3" + (a, b)
}
scala> Foo3(1,2,3)
res2: Foo3 = Foo(1,2)
Another alternative is to have multiple parameter lists.
scala> case class Foo3(a: Int, b: Int)(c: Int)
defined class Foo3
scala> Foo3(1,2)(3)
res3: Foo3 = Foo3(1,2) // only the arguments of the first argument list are printed
scala> Foo3(1,2)(3).productArity
res4: Int = 2 // product arity is number of arguments of the first argument list
CODE:
object CaseTest {
trait TSV extends Product { // #1
override def toString:String = productIterator.mkString("\t") // #2
}
case class A(name:String, age:Int) extends TSV // #3
case class B(a:A, b:Boolean) extends TSV
def main(args: Array[String]) {
val a = A("Me", 23)
val b = B(A("Other", 45), b = true)
println(a)
println(b)
}
}
OUTPUT:
Me|23
Other|45|true
PROCESS:
Create a Trait that extends Product
Override the toString method in the new Trait
Extends all your case classes from the new Trait
You don't really need to extends from Product, but it will give you access to a lot of the functionality of the case classes like the productIterator.

Does having a private constructor on a value class negate the benefits of a value class?

I'm thinking of making a value class that has some guard on how it can be instantiated. For the sake of example, say I want a non-negative integer:
class NonNegInt private (val value: Int) extends AnyVal
object NonNegInt {
def apply(value: Int): Try[NonNegInt] = Try {
if (value >= 0) new NonNegInt(value) else throw new IllegalArgumentException("non-negative integers only!")
}
}
My only worry is that the private constructor may make it impossible for the scala compiler to treat the NonNegInt as a primitive int. Is this true?
If "treat as a primitive" here means "avoid allocation", then this indeed will not work, but not because of a private constructor.
As mentioned in Value Classes Guide
Another instance of this rule is when a value class is used as a type argument. For example, the actual Meter instance must be created for even a call to identity.
def identity[T](t: T): T = t
identity(Meter(5.0))
Basically, because identity[T] is parametrized, invoking it on a value type requires an allocation of an instance. Try[T] is the same situation: Try { ... } "block" is an invocation of a parametrized function Try.apply[T] with T being NonNegInt. This call will require an allocation of NonNegInt instance.
This is a hint:
scala> implicit class X private (val i: Int) extends AnyVal { def doubled = 2 * i }
<console>:7: error: constructor X in class X cannot be accessed in object $iw
implicit class X private (val i: Int) extends AnyVal { def doubled = 2 * i }
^
And this is definitive:
$ scala -optimise
Welcome to Scala version 2.11.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_11).
Type in expressions to have them evaluated.
Type :help for more information.
scala> :pa
// Entering paste mode (ctrl-D to finish)
class X private (val i: Int) extends AnyVal { def doubled = 2 * i }
object X { #inline def apply(i: Int) = new X(i) }
// Exiting paste mode, now interpreting.
defined class X
defined object X
scala> X(42).doubled
warning: there was one inliner warning; re-run with -Yinline-warnings for details
res0: Int = 84
You can use :javap -prv - to verify that there was an allocation.
But this is a better trick:
scala> case class X private (val i: Int) extends AnyVal { def doubled = 2 * i }
defined class X
scala> X(42).doubled
res1: Int = 84
scala> :javap -prv -
[snip]
public $line7.$read$$iw$$iw$();
flags: ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: aload_0
1: invokespecial #19 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #21 // Field MODULE$:L$line7/$read$$iw$$iw$;
8: aload_0
9: getstatic #26 // Field $line6/$read$$iw$$iw$X$.MODULE$:L$line6/$read$$iw$$iw$X$;
12: bipush 42
14: invokevirtual #30 // Method $line6/$read$$iw$$iw$X$.doubled$extension:(I)I
17: putfield #17 // Field res1:I
20: return
Footnote:
scala> case class X[A <: X[A]] private (val i: Int) extends AnyVal { def doubled = 2 * i }
defined class X
scala> X(42).doubled
res2: Int = 84
Your example code is making your actual question ambiguous. Your example code wraps the Int in a Try. If instead of using Try, you used a require statement in the companion object, then it's my understanding the code below would work (without losing the "primitive" benefits extending AnyVal offers). This would give you a runtime exception if/when there is an attempt to produce a negative value. The code uses a private constructor on the case class extending AnyVal. Then it uses the case class's companion object's apply method to enforce runtime constraints via a require statement.
If you really need to wrap the value using a Try, you can provide an additional companion object constructor to wrap apply to capture the exception. However, as is pointed out in other answers, you lose the AnyVal "primitive" quality when it is "contained" by a Try, Option, Either, etc.
WARNING: The code below will not compile in the REPL/Scala Worksheet. A case class extending AnyVal must be a top-level class; i.e. cannot be nested within the scope of another class, trait, or object. And both the REPL and Scala Worksheet are implemented by pushing all the code into an invisible containing class before executing.
object PositiveInt {
def apply(value: Int): PositiveInt = {
require(value >= 0, s"value [$value] must be greater than or equal to 0")
new PositiveInt(value)
}
def tryApply(value: Int): Try[PositiveInt] =
Try(apply(value))
}
case class PositiveInt private(value: Int) extends AnyVal
val positiveTestA = PositiveInt(0)
val positiveTestB = PositiveInt(1)
val positiveTestD = PositiveInt.tryApply(-1)) //returns Failure
val positiveTestD = Try(PositiveInt(-1)) //returns Failure
val positiveTestC = PositiveInt(-1) //throws required exception

trait composition will be ignored on new instance if it is already composed in the class level

Here is the code:
trait Foo {
def get(x: Int): Int
}
trait Simple extends Foo {
override def get(x: Int): Int = x
}
trait Add15 extends Foo {
abstract override def get(x: Int): Int = x + 15
}
trait Add30 extends Foo {
abstract override def get(x: Int): Int = {
super.get(x) + 30
}
}
class Queue extends Simple with Add15 with Add30
new Queue with Add30 get 0 // same as new Queue get 0, because with Add30 is ignored
I just wonder that is it better to have a compilation error instead of ignoring it ? it is just like
class Queue extends Simple with Add15 with Add30 with Add30 will have a compilation error
Many thanks in advance
The with is not ignored.
The spec for new t actually says that new Queue with Add30 is equivalent to:
{ class a extends Queue with Add30 ; new a }
Sure, but does it actually compile to that?
In fact:
scala> new Queue with Add30
res8: Queue with Add30 = $anon$1#aa21042
scala> :javap -prv -
Binary file res8 contains $line18.$read$$iw$$iw$
[snip]
private final $line12.$read$$iw$$iw$Queue res8;
flags: ACC_PRIVATE, ACC_FINAL
[snip]
public $line18.$read$$iw$$iw$();
flags: ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: aload_0
1: invokespecial #19 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #21 // Field MODULE$:L$line18/$read$$iw$$iw$;
8: aload_0
9: new #23 // class $line18/$read$$iw$$iw$$anon$1
12: dup
13: invokespecial #24 // Method $line18/$read$$iw$$iw$$anon$1."<init>":()V
16: putfield #17 // Field res8:L$line12/$read$$iw$$iw$Queue;
19: return
So the resulting value is just a Queue, but you're instantiating an anonymous subclass that trivially extends it. I'm too lazy (I mean busy) to try -optimize.
You can turn the question around and ask why does with T with T complain about trait T is inherited twice? Can't linearization handle the redundancy?
I think the second case, where the a disappears from the linearization, is for the case:
scala> class X
defined class X
scala> trait Y extends X
defined trait Y
scala> new X with Y
res15: X with Y = $anon$1#5af97169
where you're mixing in a Y that already extends X.
But now I must use the napkin (serviette) on which I was scribbling for its primary use case and go back to what I was doing before.

Value class instantiation?

trait IntWrapper[#specialized(Long, Int) T] extends Any {
def value: T
type I = Integral[T]
implicit def leFromInt(i: Int)(implicit i2: I): T = i2.fromInt(i)
implicit def leToInt(t: T)(implicit i2: I): Int = i2.toInt(t)
def nums(implicit i: I) = {
import i._
#tc def inner(remaind: T, acc: List[Int]): List[Int] = quot(remaind, 10) match {
case that if equiv(0, that) => rem(remaind, 10)::acc
case that => inner(that, rem(remaind, 10)::acc)
}
inner(value, Nil)
}
}
object Test {
implicit class intw(val value: Int) extends AnyVal with IntWrapper[Int]
def main(args: Array[String]): Unit = {
println{
3.nums
}
}
}
Running javap -c Test$ gives
public void main(java.lang.String[]);
Code:
0: getstatic #24 // Field scala/Predef$.MODULE$:Lscala/Predef$;
3: new #26 // class Test$intw
6: dup
7: aload_0
8: iconst_3
9: invokevirtual #28 // Method intw:(I)I
12: invokespecial #31 // Method Test$intw."<init>":(I)V
15: getstatic #36 // Field scala/math/Numeric$IntIsIntegral$.MODULE$:Lscala/math/Numeric$IntIsIntegral$;
18: invokevirtual #40 // Method Test$intw.nums:(Lscala/math/Integral;)Lscala/collection/immutable/List;
21: invokevirtual #44 // Method scala/Predef$.println:(Ljava/lang/Object;)V
24: return
Given that
A value class is actually instantiated when:
a value class is treated as another type. a value class is assigned to
an array. doing runtime type tests, such as pattern matching.
Why is intw instantiated?
The nums method is not defined in intw, but in its parent trait IntWrapper, and when you invoke a method from a trait that a value class inherits from initialization is required. This is an instance of "a value class is treated as another type". See the final part of the Introduction and the first part of Allocation Details in Value Classes and Universal Traits on the Scala website.
In this particular case, the initialization could be eliminated, but the compiler isn't currently smart enough to do this. It is discused briefly at the end of the Value Classes proposal.