Functions Overloading in interface and classes - how to? - class

I have this interface :
interface IPoint {
getDist(): string;
getDist(x: number): any;
}
and I need a class to implement it but I can't get the right syntax to implement the getDist() method
in the class..
class Point implements IPoint {
// Constructor
constructor (public x: number, public y: number) { }
pointMethod() { }
getDist() {
Math.sqrt(this.x * this.x + this.y * this.y);
}
// Static member
static origin = new Point(0, 0);
}
it says:
Class 'Point' declares interface 'IPoint' but does not implement it:
Types of property 'getDist' of types 'Point' and 'IPoint' are
incompatible:Call signatures of types '() => void' and '{ (): string;
(x: number): any; }' are incompatible
What's the proper way to do this?
Thanks

When you declare the function in the class you need to decorate it with the overloads:
getDist(): string;
getDist(x: number): any;
getDist(x?: number): any {
// your code
}

This answer describes how to implement method overloading in TypeScript, and it's not pretty:
interface IPoint {
getDist(): string;
getDist(x: number): any;
}
class Point implements IPoint {
// Constructor
constructor (public x: number, public y: number) { }
pointMethod() { }
getDist(x?: number) {
if (x && typeof x == "number") {
return 'foo';
} else {
return 'bar';
}
}
}
N.B. with the particular combination of declared return types in the interface, you are limited to returning strings from getDist.

also you can use the default value
interface Foo{
next()
next(steps: number)
prev()
prev(steps: number)
}
next(steps: number = 1) {
// ...
}
prev(steps: number = 1) {
// ...
}

The following is a variation on some of the above
class Position {
x: number;
y: number;
constructor(x : number = 0, y : number = 0) {
this.x = x;
this.y = y;
}
}
class Pen {
colour: string;
constructor(colour: string) {
this.colour = colour;
}
}
class PlottingHead {
isPenUp: boolean;
pen: Pen;
position: Position;
constructor() {
this.penUp();
}
move(p: Position): void;
move(x: number, y: number): void;
move(x: number | Position, y?: number): void {
if (typeof x === "number")
{
x = new Position(x, y);
}
this.penUp();
this.position = x;
}
draw(x: number | Position, y?: number): void {
if (typeof x === "number")
{
x = new Position(x, y);
}
this.penDown();
this.position = x;
}
penDown(): void {
this.isPenUp = false;
}
penUp(): void {
this.isPenUp = true;
}
onChangePen(newPen: Pen) {
this.penUp();
this.pen = newPen;
}
}
The move function takes either a single position object or a pair of numeric values. This can obviously be extended as required.

Related

Flutter class definition with 'Object' class member

in my Flutter project, I want to decide class member type during execution. For this, I wrote the following code with the help of this entry: https://github.com/flutter/flutter/issues/17766 But I cannot access function printt(). It gives error: The method 'printt' isn't defined for the type 'Object'.
void main() {
Merchant merchant = Merchant('A');
merchant.mp!.printt(); // this line gives error: The method 'printt' isn't defined for the type 'Object'.
}
class Merchant {
Object? mp;
Merchant(String mpStr) {
if (mpStr == 'A') mp = createInstanceOf<A>();
if (mpStr == 'B') mp = createInstanceOf<B>();
}
T? createInstanceOf<T>() {
final factories = <Type, T Function()>{
A: () => A() as T,
B: () => B() as T,
};
final createInstance = factories[T];
return createInstance?.call(); // Same as createInstance() but null safety
}
}
class A {
void printt() {
print('I am function of class A');
}
}
class B {
void printt() {
print('I am function of class B');
}
}
Like #Yannis mentioned, create an abstract class, let's say PrintT, with all common methods of A and B and set mp as this type. Then, set both class A and B to implement it. The code is going to be the following:
Check out the live demo on DartPad.
void main() {
Merchant merchant = Merchant('A');
merchant.mp!.printt();
}
class Merchant {
PrintT? mp;
Merchant(String mpStr) {
if (mpStr == 'A') mp = createInstanceOf<A>();
if (mpStr == 'B') mp = createInstanceOf<B>();
}
T? createInstanceOf<T>() {
final factories = <Type, T Function()>{
A: () => A() as T,
B: () => B() as T,
};
final createInstance = factories[T];
return createInstance?.call(); // Same as createInstance() but null safety
}
}
abstract class PrintT {
void printt();
}
class A implements PrintT {
void printt() {
print('I am function of class A');
}
}
class B implements PrintT {
void printt() {
print('I am function of class B');
}
}

C++ overloading operator, compiler doesn't see the operator

CMagazin.h
class CMagazin
{
char *m_nume;
list<CProdus*>List_produse;
public:
void printExpirabile( const char* data);
~CMagazin();
};
CMagazin.cpp
void CMagazin::printExpirabile(const char *xdata)
{
list<CProdus*>::iterator it;
for (it = List_produse.begin(); it != List_produse.end(); ++it)
{
CProdus* p = *it;
if (p->get_tip()=='A')
{
**if (p > xdata)**->this problem
}
}
}
CAliment.h
class CAliment :
public CProdus
{
char *m_expirare;
public:
bool operator >(const char*date);
~CAliment();
};
CAliment.cpp
bool CAliment::operator>(const char * date)
{
if (atoi(this->m_expirare) < atoi(date))
{
return 1;
}
else
{
return 0;
}
}
its about ">" operator.in CMagazin.cpp dont use my operator...i need help.
what can i do?I need ">" in CMagazin class. class CAliment its a class derived from CProdus.
Answer is: in Class CProdus the operator must be declared virtual, and in
CMagazin.cpp
void CMagazin::printExpirabile(const char *xdata)
{
list<CProdus*>::iterator it;
for (it = List_produse.begin(); it != List_produse.end(); ++it)
{
CProdus* p = *it;
if (p->get_tip()=='A')
{
if (p->operator>( xdata))-> make this!
{
p->print();
}
}
}
}
CProdus*p - is a pointer , need to have object for use this operator -> Try (*p)>xdata
void CMagazin::printExpirabile(const char *xdata)
{
list<CProdus*>::iterator it;
for (it = List_produse.begin(); it != List_produse.end(); ++it)
{
CProdus* p = *it;
if (p->get_tip()=='A')
{
if ((*p)>( xdata))-> make this!
{
p->print();
}
}
}
}

Haxe macro to set null to calling instance?

Is there a way of setting a null to calling instance as a result of some "macro-function-call"?
Like so:
class A {
// ...
macro function DestroyItself() {
// ...
}
}
var a:A = new A();
// ...
a.DestroyItself();
trace(a); // "null"
Yep:
macro public function destroy(self:Expr) {
return macro $self = null;
}
// ...
a.destroy();
In non-static macro functions first Expr argument is a ref to caller instance.
Once approach would be to create generic tools to null any instance.
package ;
class Tools
{
/**
* Simply assigns null to the instance
* See more at: http://code.haxe.org/category/macros/generating-code-in-a-macro.html
*
* #param instance - Any
* #return haxe.macro.Expr
*/
public static macro function nullMe(instance : haxe.macro.Expr.ExprOf<Dynamic>) : haxe.macro.Expr
{
return macro {
${instance} = null;
};
}
}
This use the using Tools; to generically null any instance, but I would not recommend this. I'd use the per-class approach.
Main.hx
package ;
class Main {
static function main() {
// Construct
var instance = new SomeClass();
// Destroy
instance.destroy();
// Trace null
trace(instance);
}
}
SomeClass.hx
package ;
class SomeClass
{
public function new()
{
trace("Hello from SomeClass!");
}
private function preDestroy()
{
trace("The end is nigh!");
}
public macro function destroy(self : haxe.macro.Expr) : haxe.macro.Expr
{
return macro {
#:privateAccess ${self}.preDestroy();
${self} = null;
};
}
}
Compiled JS
// Generated by Haxe 3.4.2
(function () { "use strict";
var Main = function() { };
Main.main = function() {
var instance = new SomeClass();
instance.preDestroy();
instance = null;
console.log(instance);
};
var SomeClass = function() {
console.log("Hello from SomeClass!");
};
SomeClass.prototype = {
preDestroy: function() {
console.log("The end is nigh!");
}
};
Main.main();
})();

TYpescript : Static methods on Function as class

I have a fn that inherit an existing fn ( take Angular1 $q for example )
//$q original behavior
var defer = $q.defer();
defer.promise.then(function(result){})
//or
$q( (resolve, reject) => {
//promise execution here
}).then(function(result){});
If I want to decorate it, I would do :
var Qdecorator = function($delegate) {
var Q = function(resolver:any): any {
//do some extra stuff here
return $delegate.apply($delegate, arguments);
}
//Assign the static methods here:
Q.defer = function() {
//do some stuff
return $delegate.defer.apply($delegate, []);
}
//same goes for race, when, resole reject and so on
return Q;
}
Problem is that typescript complains about
Property defer, race, when, resolve, etc... does not exist on type '(resolver: any) => any'
I tried to use the IQService, and IPromise with no luck, btu I'd like to raise a more global question :
How do I define late static methods on function() that return an object without using new
I am copying pasting the answer to my question from this link:
https://www.typescriptlang.org/docs/handbook/interfaces.html
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = <Counter>function (start: number) { };
counter.interval = 123;
counter.reset = function () { };
return counter;
}
let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;

Create Class From Hybrid Interface Type

First of all, I'm very new to TS, and during my reading in
http://www.typescriptlang.org/Handbook I stop at trying to understand how Hybrid Types Interface works.
In the example of the TS:
interface ICounter {
(start: number): string;
interval: number;
reset(): void;
}
var c: ICounter;
c(10);
c.reset();
c.interval = 5.0;
So, the problem was when I tried to write a class using this interface, the problem was the line:
(start: number): string;
First I thought that this line represents a function so tried to create:
class Test implements ICounter {
interval: number;
reset(): void { }
start(start: number): string {
return "";
}
}
But this keep showing that "Types Test and ICounter have incompatible signatures", so what I'm missing here? I thought that interfaces should work the same way for classes and variables.
ICounter represents a function that has two properties—interval and reset.
This line in the interface...
(start: number): string;
...describes a way to call the function. It's shown in the example as:
c(10)
The other lines describe the function's properties—interval and reset.
c.reset();
c.interval = 5.0;
As stated in the handbook, this is used for representing JavaScript libraries that do this. So for example, the above could represent the following JavaScript code:
function counter(start) {
alert(start);
return "some string";
}
counter.reset = function() { alert('reset called'); };
counter.interval = 1;
In addition to all this, note that the class you described could be represented by the following interface:
interface ITest {
interval: number;
reset: () => void;
start: (start: number) => string;
}
class implies that you will create instances via new operator. new creates object, not function, so it is impossible to implement class, which instances can called as function. You can do something like this:
interface ICounterObject {
interval: number;
reset(): void;
}
interface ICounter extends ICounterObject {
(start: number): string;
__proto__: ICounterObject;
}
class Test implements ICounterObject {
static createCounter(): ICounter {
var counter = <ICounter>function (start: number): string {
return "";
};
counter.__proto__ = Test.prototype;
return counter;
}
interval: number;
reset(): void { }
}
Note, __proto__ is from ES6, but de-facto is supported in ES5 browsers. If you want to use function prototype members (e.g call and apply) mix prototypes:
function mixWithFunc<T extends Function>(obj: { __proto__?}, func: T) {
var objProto = <{ constructor }>obj.__proto__;
var objClass = <{ __mixedProto__ }>objProto.constructor;
var proto = <typeof obj>objClass.__mixedProto__;
if (!proto) {
proto = {};
proto.__proto__ = objProto;
['call', 'apply', 'bind'].forEach(p => proto[p] = Function.prototype[p]);
objClass.__mixedProto__ = proto;
}
(<typeof obj>func).__proto__ = proto;
Object.getOwnPropertyNames(obj).forEach(p => func[p] = obj[p]);
return func;
}
interface ICounter extends Counter {
(start: number): string;
}
class Counter {
static create() {
var self: ICounter = mixWithFunc(
new Counter(),
<ICounter>function (start: number) {
return "started with interval: " + self.interval;
});
return self;
}
interval = 1000;
reset() { this.interval = 0; }
}
Of course you can just add members to each instance of your function instead of prototyping.