Why I Can Not Call Super in Define_Method with Overloading Method

Why I can not call super in define_method with overloading method?

The error message is quite descriptive. You need to explicitly pass arguments to super when you call it inside of define_method block:

mem[args] = super(*args)

Scala - Why are overloaded methods not called based on runtime class?

Static overload resolution is easy to reason about: for the methods that are applicable, a method is selected as "more specific" just based on the signatures.

However,

scala> Seq((new A(), ShowA), (new B(), ShowB))
res0: Seq[(Base, ShowBase)] = List((A@2b45f918,ShowA$@7ee4acd9), (B@57101ba4,ShowB$@6286d8a3))

in ShowBase there is no overload.

scala> res0 foreach {
| case (obj: A, showImpl) => println(showImpl.show(obj), obj.getClass.getSimpleName)
| case (obj: B, showImpl) => println(showImpl.show(obj), obj.getClass.getSimpleName)
| }
java.lang.InternalError: Malformed class name
at java.lang.Class.getSimpleName(Class.java:1180)
at $anonfun$1.apply(<console>:17)
at $anonfun$1.apply(<console>:16)
at scala.collection.immutable.List.foreach(List.scala:383)
... 38 elided

Oh yeah, don't use getSimpleName from Scala.

scala> res0 foreach {
| case (obj: A, showImpl) => println(showImpl.show(obj), obj.getClass)
| case (obj: B, showImpl) => println(showImpl.show(obj), obj.getClass) }
(Base,class $line4.$read$$iw$$iw$A)
(Base,class $line5.$read$$iw$$iw$B)

OTOH,

scala> class ShowBase extends Show[Base] {
| override def show(obj: Base): String = "Base"
| def show(a: A) = "A" ; def show(b: B) = "B" }
defined class ShowBase

scala> Seq((new A(), new ShowBase), (new B(), new ShowBase))
res3: Seq[(Base, ShowBase)] = List((A@15c3e01a,ShowBase@6eadd61f), (B@56c4c5fd,ShowBase@10a2918c))

scala> res3 foreach {
| case (obj: A, showImpl) => println(showImpl.show(obj), obj.getClass)
| case (obj: B, showImpl) => println(showImpl.show(obj), obj.getClass) }
(A,class $line4.$read$$iw$$iw$A)
(B,class $line5.$read$$iw$$iw$B)

It's easy to imagine a macro that generates the partial function for a given interface with an overloaded method show.

Another idea, not necessarily a great one, is to let the compiler do the selection at runtime.

This is currently awkward to demonstrate in REPL. You have to import any symbols you want to use from the objects that litter your REPL history. See the issue.

scala> def imps = $intp.definedSymbolList map (s => $intp.global.exitingTyper { s.fullName }) mkString ("import ", "\nimport ", "\n")
imps: String

scala> tb.eval(tb.parse(s"$imps ; ShowA show a"))
res15: Any = A

Hey, it worked!

Or, go into power mode, which sets the current phase at typer and gives you intp without the funky dollar sign. Because do we really need more dollars?

scala> :power
** Power User mode enabled - BEEP WHIR GYVE **
** :phase has been set to 'typer'. **
** scala.tools.nsc._ has been imported **
** global._, definitions._ also imported **
** Try :help, :vals, power.<tab> **

scala> def imps = intp.definedSymbolList map (_.fullName) mkString ("import ", "\nimport ", "\n")
imps: String

scala> tb.eval(tb.parse(s"$imps ; ShowA show a"))
res17: Any = A

If you want to see your unsanitized imports:

scala> intp.isettings.unwrapStrings = false
intp.isettings.unwrapStrings: Boolean = false

scala> imps
res11: String =
"import $line2.$read.$iw.$iw.$intp
import $line3.$read.$iw.$iw.Base
import $line3.$read.$iw.$iw.A
import $line3.$read.$iw.$iw.B
import $line4.$read.$iw.$iw.Show
import $line5.$read.$iw.$iw.ShowA
[snip]

Once more:

scala> abstract class Base ; class A extends Base ; class B extends Base
defined class Base
defined class A
defined class B

scala> trait Show[T <: Base] { def show(obj: T): String }
defined trait Show

scala> class ShowBase extends Show[Base] { override def show(obj: Base): String = "Base" }
defined class ShowBase

scala> object ShowA extends ShowBase { def show(obj: A): String = "A" }
defined object ShowA

scala> :power
** Power User mode enabled - BEEP WHIR GYVE **
** :phase has been set to 'typer'. **
** scala.tools.nsc._ has been imported **
** global._, definitions._ also imported **
** Try :help, :vals, power.<tab> **

scala> def imps = intp.definedSymbolList map (_.fullName) mkString ("import ", "\nimport ", "\n")
imps: String

scala> import tools.reflect._
import tools.reflect._

scala> val tb = reflect.runtime.currentMirror.mkToolBox()
tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = scala.tools.reflect.ToolBoxFactory$ToolBoxImpl@24e15d95

Did I mention the import mechanism is awkward?

scala> val a = new A
a: A = A@1e5b2860

scala> tb.eval(tb.parse(s"$imps ; ShowA show a"))
res0: Any = A

scala> ShowA show (a: Base)
res1: String = Base

scala> tb.eval(tb.parse(s"$imps ; ShowA show (a: Base)"))
res2: Any = Base

scala> val a: Base = new A
a: Base = A@7e3a93ce

scala> tb.eval(tb.parse(s"$imps ; ShowA show a"))
scala.tools.reflect.ToolBoxError: reflective compilation has failed:

reference to a is ambiguous;
it is imported twice in the same scope by
import a
and import a
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.throwIfErrors(ToolBoxFactory.scala:315)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.wrapInPackageAndCompile(ToolBoxFactory.scala:197)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.compile(ToolBoxFactory.scala:251)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$$anonfun$compile$2.apply(ToolBoxFactory.scala:428)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$$anonfun$compile$2.apply(ToolBoxFactory.scala:421)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$.liftedTree2$1(ToolBoxFactory.scala:354)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$.apply(ToolBoxFactory.scala:354)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.compile(ToolBoxFactory.scala:421)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.eval(ToolBoxFactory.scala:443)
... 37 elided

So, if you decide what type you want to select on:

scala> val x: Base = new A
x: Base = A@2647e550

scala> tb.eval(tb.parse(s"$imps ; ShowA show x"))
res4: Any = Base

scala> tb.eval(tb.parse(s"$imps ; ShowA show (x.asInstanceOf[A])"))
res5: Any = A

Implicit argument passing of super from method defined by define_method() is not supported

The super above passed all parameters (see this recent question).

As the error message states, you must here "specify all arguments explicitly". Replace super with super(label, *args).

Overload method with subclasses as parameters but have the method called as the superclass

Yes instanceof and getclass would make your class dependent upon specific types and using such practices are not too good.

But by having methods accepting Dog or Cat you again end up depending upon the concrete specific implementation.

Better way is Define method in Animal interface performAction() . Provide implementation in both Dog and Cat. Now iterate your List of Animals and just invoke performAction() and polymorphically as per actual instance either Dog or Cat implemented method would be called. Later even if there is another implementation of Animal added in code you need not modify your code.

This way you would be having Dog related logic in Dog class, Cat related logic in Cat class and not in any outside different class. This will help in respecting OCP and SRP (Open close and Single Responsibility principles).

Also in case you wish to perform behavior later and your case is such that you know your implementations are fixed and want the using code to inject behavior later then I would recommend Visitor pattern, but still I feel this should not be abused, (design pattern are often not used but abused) sometime we force a pattern when not needed. Visitor pattern uses polymorphic to dispatch the first call to specific instance from where second dispatch calls the overloaded methods in class implementing the Visitor interface. (name can be different, I have mentioned Visitor to imply class implementing the concept of visitor) . Go for Visitor pattern like implementation only if needed and normal above polymorphic based approach do not fit the situation.

Is parameter's default value still valid in sub class?

Yes, default parameters are inherited automatically by subclasses. In invoking a.print(), "abc" is passed as the str parameter.

See section on overriding: https://docs.scala-lang.org/sips/named-and-default-arguments.html

Can a method in sub class overloading a method in super class?

Taking a more formal approach, the Java Language Specification for Java 7 states:

If two methods of a class (whether both declared in the same class, or both inherited by a class, or one declared and one inherited) have the same name but signatures that are not override-equivalent, then the method name is said to be overloaded.

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.9

I would point your friend to this link.

So, in short, in your example, the hello method is indeed overloaded.

Declaring abstract method in TypeScript

The name property is marked as protected. This was added in TypeScript 1.3 and is now firmly established.

The makeSound method is marked as abstract, as is the class. You cannot directly instantiate an Animal now, because it is abstract. This is part of TypeScript 1.6, which is now officially live.

abstract class Animal {
constructor(protected name: string) { }

abstract makeSound(input : string) : string;

move(meters) {
alert(this.name + " moved " + meters + "m.");
}
}

class Snake extends Animal {
constructor(name: string) { super(name); }

makeSound(input : string) : string {
return "sssss"+input;
}

move() {
alert("Slithering...");
super.move(5);
}
}

The old way of mimicking an abstract method was to throw an error if anyone used it. You shouldn't need to do this any more once TypeScript 1.6 lands in your project:

class Animal {
constructor(public name) { }
makeSound(input : string) : string {
throw new Error('This method is abstract');
}
move(meters) {
alert(this.name + " moved " + meters + "m.");
}
}

class Snake extends Animal {
constructor(name) { super(name); }
makeSound(input : string) : string {
return "sssss"+input;
}
move() {
alert("Slithering...");
super.move(5);
}
}

How to define method to act as decorator for other methods inside the same class in Python?

I managed to wrap my head around this problem, but at the end I simply choose to extract _write out class to as regular decorator function.

This solution breaks many rules of The Zen of Python, if there's better solution I'll accept it:

import pathlib
import json

DATABASE_PATH = pathlib.Path('db.json')

class Database:

def __init__(self):
self.data = dict()

def _write(fn):
def decorator(self, **kwargs):
_response = fn(self, **kwargs)
with DATABASE_PATH.open(mode='w', encoding='utf-8') as _db:
json.dump(self.data, _db, indent=4)
return _response
return decorator

@_write
def insert(self, **kwargs):
if all(k for k in kwargs if k in ('name', 'surname')): # Insert if contains all values.
self.data.update(**kwargs)
return True
return False # Insert failed.

if __name__ == '__main__':
db = Database()
db.insert(name='Dummy-Name', surname='Dummy-Surname')


Related Topics



Leave a reply



Submit