Overriding parameter types? - oop

I would like to override the parameter type of a method in its subclasses, I thought generics could be used for this but that does not seem to work (at least not the way I am doing it).
abstract class A {
bool someMethod<T>(T x);
}
Then override it like so:
class B extends A {
bool someMethod<bool>(bool x) {
// error: isn't a valid override
}
}
I have had to default to using type dynamic x for the parameter type, but that forfeits runtime safety checks and means a lot of type checking whenever the method is implemented.
Is this type of extension possible?

It's possible, but not the way you do it.
What you declare is a generic method, where each invocation gets to pass the type argument to the function.
What you probably want is:
abstract class A<T> {
bool someMethod(T x);
}
class B extends A<bool> {
bool someMethod(bool x) {
return true;
}
}
That makes the type a parameter of the subclass, not the method, so each subclass can define its own type.
(Here you get into problems with Dart's covariant generics, because you can write:
A<Object> a = B();
a.someMethod("a"); // run-time error.
Your type variable occurs only in places where a value of that type is needed, not where one is provided, so casting to the superclass A<Object> make the method more permissive than it can support. The compiler inserts a run-time type check on the argument, which is what the example code here hits.)

Related

Extend calculator with complex and rational module(using dynamic binding)

I already made calculator that can compute with integers and real numbers(i made it with go).
Then I want to make it possible to calculate complex and rational numbers by adding those modules.
(it can also calculate when types are mixed)
It can be easy if I check types of operands every time(runtime) and take care of each case, but I want to solve it with dynamic binding. Guys can you tell me the idea of how to solve this problem
I think by dynamic typing, you're probably referring to how in eg C++ and Java, dynamic binding is essentially having reference to a base class that can point to a derived class (because the derived class "is a" base class).
One might say that the base class defines the interface behind which derived classes morph. If the derived classes replace methods of the base class, a reference to the base class can still access those methods in the derived class.
Base class can define some methods to provide some "base" functionality to its derived classes. If those classes don't redefine the method, the base class's method can be called.
In go, both these concepts exist, but they're quite different.
Go has an explicit interface keyword that defines method signatures but no methods. Any value implicitly satisfies that interface if it has methods of the same name with the same signature.
type LivingBeing interface {
TakeInEnergy()
ExpelWaste()
}
The interface type becomes a valid type in the code. We can pass an interface to a function, and without knowing the type satisfying that interface, can call its methods:
func DoLife(being LivingBeing) {
being.TakeInEnergy()
being.ExpelWaste()
}
This is valid code, but not complete code. Unlike with base classes in other languages, interfaces cannot define functions, only their signatures. It is purely and only an interface definition. We have to define the types that satisfy the interface separately from the interface itself.
type Organism struct{}
func (o *Organism) TakeInEnergy() {}
func (o *Organism) ExpelWaste() {}
We now have a type organism that satisfies LivingBeing. It is something like a base class, but if we wanted to build on it, we can't use subclassing because Go doesn't implement it. But Go does provide something similar called embedding types.
In this example I'll define a new organism, Animal, that draws ExpelWaste() from LivingBeing, but defines its own TakeInEnergy():
type Animal struct {
Organism // the syntax for an embedded type: type but no field name
}
func (a *Animal) TakeInEnergy() {
fmt.Printf("I am an animal")
}
What isn't obvious from that code is that because Animal's Organism is not a named field, its fields and methods are accessible directly from Animal. It's almost as if Animal "is an" organism.
However it is *not * an organism. It is a different type, and it would be more accurate to think of object embedding as syntactic sugar to automatically promote Organism's fields and methods to Animal.
Since go is statically and explicitly typed, DoLife cannot take an Organism and then be passed an Animal: it doesn't have the same type:
/* This does not work. Animal embeds organism, but *is not* an organism */
func DoLife(being *Organism) {
being.TakeInEnergy()
being.ExpelWaste()
}
func main() {
var a = &Animal{Organism{}}
DoLife(&Animal{})
}
cannot use &Animal{} (type *Animal) as type *Organism in argument to DoLife
That's why interface exists - so that both Organism and Animal (and indeed, even Plant or ChemotrophBacteria) can be passed as a LivingBeing.
Putting it all together, here's the code I've been working from:
package main
import "fmt"
type LivingBeing interface {
TakeInEnergy()
ExpelWaste()
}
type Organism struct{}
func (o *Organism) TakeInEnergy() {
}
func (o *Organism) ExpelWaste() {}
type Animal struct {
Organism
}
func DoLife(being LivingBeing) {
being.TakeInEnergy()
being.ExpelWaste()
}
func (a *Animal) TakeInEnergy() {
fmt.Printf("I am an animal")
}
func main() {
var a = &Animal{Organism{}}
DoLife(a)
}
There are a few caveats:
Syntactically, If you want to declare an embedded literal you must explicitly provide its type. In my example Organism has no fields so there's nothing to declare, but I still left the explicit type in there to point you in the right direction.
DoLife can call the right TakeInEnergy on a LivingBeing, but Organism's methods cannot. They see only the embedded Organism.
func (o *Organism) ExpelWaste() {
o.getWaste() //this will always be Organism's getWaste, never Animal's
}
func (o *Organism)getWaste() {}
func (a *Animal)getWaste() {
fmt.Println("Animal waste")
}
Simlarly if you pass only the embedded part, then it's going to call its own TakeInEnergy(), not that of Animal; there's no Animal left!
func main() {
var a = &Animal{Organism{}}
DoLife(&a.Organism)
}
In summary,
Define explict interface and use that type wherever you want "polymorphic" behavior
Define base types and embed them in other types to share base functionality.
Don't expect the "base" type to ever "bind" to functions from the "derived" type.

Expression 'classLevel' of type 'Any' cannot be invoked as a function. The function 'invoke()' is not found

Consider the following class:
class Test {
val classLevel = object {
operator fun invoke() = println("test class level property invocaton")
}
fun foo() {
val functionLevel = object {
operator fun invoke() = println("test invocation")
}
functionLevel() // no problem
classLevel() // Expression 'classLevel' of type 'Any' cannot be invoked as a function. The function 'invoke()' is not found
}
}
Why does the second invoke, the one to the class property, not compile? It is declared the same way as in the function.
I think this is about types.
The classLevel field is of an anonymous type (a subtype of Any, created by the object expression). That type has an invoke() method.
However, that type isn't visible outside the class. So if the property has a getter (i.e. it isn't private), the getter can't return the anonymous type; it has to return the closest named type, which is Any. And Any doesn't have an invoke() method.
I'm not certain whether the code within the class will use the getter method if available, or whether the underlying field's type must exactly match that of the getter if present. But either way, the upshot is clearly that if there's a getter, referring to classLevel within the class gets you an Any reference, and so you can't call invoke() on it. (And you can't down-cast the reference to your object type, which does have invoke(), because that type doesn't have a name.)
One solution, as you found, is to make the field private; that removes the getter, and allows its underlying type to be the actual object type, which is why invoke() is then available to be called.
Another would probably be to define a named type for the object to implement.

How to force invoke method with object type input value without any type casting in a series of overloaded methods?

For example I'm having a class with three overloaded methods like this:
class MyClass
{
int sum(int i)
{
// Method implementation.
}
int sum(string x)
{
// Method implementation.
}
int sum(object o)
{
// Method implementation.
}
}
My question is when I call the sum method of MyClass by passing any value (integer, string or object) it should invoke only third method (with object type input parameter)
class MainClass
{
static void Main(string[] args)
{
MyClass obj = new MyClass();
obj.sum(10);
obj.sum("X")
}
}
You said "without type casting" but you can't, because you need some way to indicate to the compiler which version to call, and the runtime uses the type it sees to do that bit. Boxing the int as an object means the compiler will pick the object version
sum(1);//call int version
sum((object)1); //call object version
sum((string)(object)"1"); //call string version
sum((object)(int)(object)1); //call object version
First of all, let me say that if you sometimes want to call one version of the sum function when working with ints and sometimes want to call another, overloading probably isn't the right tool to use. Overloading works best when you are implementing conceptually the same operation for a number of different types, and you want the compiler to figure out automatically which function is the right one to call for each type; if you need more manual control over which function is called, you're probably better off using different names.
That said, if you're sure that this is what you want to do, you could implement the overloaded version for object in terms of another function in the public interface, as in:
class MyClass
{
int sum(int i)
{
// Method implementation.
}
int sum(string x)
{
// Method implementation.
}
int sum(object o)
{
sum_object(o);
}
int sum_object(object o)
{
// Method implementation for objects
}
}
Then, when you want to apply the object version to int and string objects, you just call sum_object directly instead.

What's the purpose of allowing the declaration of an abstract method in a non-abstract class?

According to this article, it's possible, in Dart, to define a non-abstract class to have an abstract (or not-implemented) method. The abstract method causes a warning, but does not prevent instantiation.
What's the purpose of allowing the declaration of an abstract method in a non-abstract (or concrete) class in Dart? Why was Dart designed to work in this way?
The specification is actually very explicit about declaring abstract methods in a concrete class:
It is a static warning if an abstract member m is declared or inherited in a concrete class
We wish to warn if one declares a concrete class with abstract members.
It is a static warning if a concrete class has an abstract member (declared or inherited).
They don't have any intended purpose for it, which is why they issue warnings. If you're familiar with Java: it's similar to accessing a static member via an object, which is also pointless and triggers a warning.
As for why it passes compilation, Dart uses an optional type system, which means typing concepts should not affect the semantics of the language, and that's simply what Dart is enforcing:
The purpose of an abstract method is to provide a declaration for purposes such as type checking and reflection.
The static checker will report some violations of the type rules, but such violations do not abort compilation or preclude execution.
An abstract method in a concrete class allows you to provide the type signature for a method that is implemented via noSuchMethod() instead. Providing a noSuchMethod() implementation will also silence the warning.
In strong mode, simply having an abstract method in a concrete class will result in an error, unless the class also implements the noSuchMethod() interface.
In short, the purpose of abstract methods in a concrete class is to provide type signatures for noSuchMethod() implementations. This avoids warnings for calling an unknown method and in strong mode (which is the default for dartdevc, and will be first the default and then mandatory for Dart 2.0) these type signatures are necessary for code with noSuchMethod() to even compile, unless the target is of type dynamic.
Example:
class A {
void f();
dynamic noSuchMethod(Invocation inv) => null;
}
void main() {
var a = new A();
a.f();
}
If we replace a.f() with (say) a.f(0), then this will result in an error (in strong mode) for having called the method with the wrong number of parameters. If we omit the void f() declaration, then we'll get an error that A does not have a method f(). If we omit the noSuchMethod() implementation, then the complaint will be that f() lacks a method body, even though A isn't abstract.
The following code provides a more realistic example:
import "dart:mirrors";
class DebugList<T> implements List<T> {
List<T> _delegate;
InstanceMirror _mirror;
DebugList(this._delegate) {
_mirror = reflect(_delegate);
}
dynamic noSuchMethod(Invocation inv) {
print("entering ${inv.memberName}");
var result = _mirror.delegate(inv);
print("leaving ${inv.memberName}");
return result;
}
}
void main() {
List<int> list = new DebugList<int>([1, 2, 3]);
int len = list.length;
for (int i = 0; i < len; i++) print(list[i]);
}
This example creates a debugging decorator for List<T>, showing all method invocations. We use implements List<T> to pull in the entire list interface, inheriting dozens of abstract methods. This would normally result in warnings (or in strong mode, errors) when run through dartanalyzer, as we're missing implementations for all these methods normally provided by List<T>. Providing a noSuchMethod() implementation silences these warnings/errors.
While we could also manually wrap all 50+ methods, this would be a lot of typing. The above approach also will continue to work if new methods are added to the list interface without us having to change our code.
Use cases for explicitly listing methods in a concrete class are less common, but can also occur. An example would be the addition of getters or setters to such a debugging decorator that allows us to inspect or set instance variables of the delegate. We will need to add them to the interface, anyway, to avoid warnings and errors from using them; the noSuchMethod() implementation can then implement them using getField() and setField(). Here's a variant of the previous example, using stacks instead of lists:
// main.dart
import "dart:mirrors";
import "stack.dart";
class DebugStack<T> implements Stack<T> {
Stack<T> _delegate;
InstanceMirror _mirror;
DebugStack(this._delegate) {
_mirror = reflect(_delegate);
}
dynamic _get(Symbol sym) {
// some magic so that we can retrieve private fields
var name = MirrorSystem.getName(sym);
var sym2 = MirrorSystem.getSymbol(name, _mirror.type.owner);
return _mirror.getField(sym2).reflectee;
}
List<T> get _data;
dynamic noSuchMethod(Invocation inv) {
dynamic result;
print("entering ${inv.memberName}");
if (inv.isGetter)
result = _get(inv.memberName);
else
result = _mirror.delegate(inv);
print("leaving ${inv.memberName}");
return result;
}
}
void main() {
var stack = new DebugStack<int>(new Stack<int>.from([1, 2, 3]));
print(stack._data);
while (!stack.isEmpty) {
print(stack.pop());
}
}
// stack.dart
class Stack<T> {
List<T> _data = [];
Stack.empty();
Stack.from(Iterable<T> src) {
_data.addAll(src);
}
void push(T item) => _data.add(item);
T pop() => _data.removeLast();
bool get isEmpty => _data.length == 0;
}
Note that the abstract declaration of the _data getter is crucial for type checking. If we were to remove it, we'd get a warning even without strong mode, and in strong mode (say, with dartdevc or dartanalyzer --strong), it will fail:
$ dartdevc -o main.js main.dart
[error] The getter '_data' isn't defined for the class 'DebugStack<int>' (main.dart, line 36, col 15)
Please fix all errors before compiling (warnings are okay).

How are overridden properties handled in init blocks?

I'm trying to understand why the following code throws:
open class Base(open val input: String) {
lateinit var derived: String
init {
derived = input.toUpperCase() // throws!
}
}
class Sub(override val input: String) : Base(input)
When invoking this code like this:
println(Sub("test").derived)
it throws an exception, because at the time toUpperCase is called, input resolves to null. I find this counter intuitive: I pass a non-null value to the primary constructor, yet in the init block of the super class it resolves to null?
I think I have a vague idea of what might be going on: since input serves both as a constructor argument as well as a property, the assignment internally calls this.input, but this isn't fully initialized yet. It's really odd: in the IntelliJ debugger, input resolves normally (to the value "test"), but as soon as I invoke the expression evaluation window and inspect input manually, it's suddenly null.
Assuming this is expected behavior, what do you recommend to do instead, i.e. when one needs to initialize fields derived from properties of the same class?
UPDATE:
I've posted two even more concise code snippets that illustrate where the confusion stems from:
https://gist.github.com/mttkay/9fbb0ddf72f471465afc
https://gist.github.com/mttkay/5dc9bde1006b70e1e8ba
The original example is equivalent to the following Java program:
class Base {
private String input;
private String derived;
Base(String input) {
this.input = input;
this.derived = getInput().toUpperCase(); // Initializes derived by calling an overridden method
}
public String getInput() {
return input;
}
}
class Derived extends Base {
private String input;
public Derived(String input) {
super(input); // Calls the superclass constructor, which tries to initialize derived
this.input = input; // Initializes the subclass field
}
#Override
public String getInput() {
return input; // Returns the value of the subclass field
}
}
The getInput() method is overridden in the Sub class, so the code calls Sub.getInput(). At this time, the constructor of the Sub class has not executed, so the backing field holding the value of Sub.input is still null. This is not a bug in Kotlin; you can easily run into the same problem in pure Java code.
The fix is to not override the property. (I've seen your comment, but this doesn't really explain why you think you need to override it.)
The confusion comes from the fact that you created two storages for the input value (fields in JVM). One is in base class, one in derived. When you are reading input value in base class, it calls virtual getInput method under the hood. getInput is overridden in derived class to return its own stored value, which is not initialised before base constructor is called. This is typical "virtual call in constructor" problem.
If you change derived class to actually use property of super type, everything is fine again.
class Sub(input: String) : Base(input) {
override val input : String
get() = super.input
}