I would like to override >= operator in Groovy, have found this page, but I am still not sure how to do it. I have a class Banknote with properties serial and amount and I wish to implement comparison bases on the amount property.
You don't override the >= operator, you implement compareTo:
class Foo implements Comparable {
int val
int compareTo(Object o) { return val <=> ((Foo) o).val }
}
f1 = new Foo(val: 5)
f2 = new Foo(val: 10)
println f1 <= f2
=> true
Related
Let's say I have:
class Test<T> {
void method() {
if (T is int) {
// T is int
}
if (T == int) {
// T is int
}
}
}
I know I can override == operator but what's the main difference between == and is in Dart if I don't override any operator.
Edit:
Say I have
extension MyIterable<T extends num> on Iterable<T> {
T sum() {
T total = T is int ? 0 : 0.0; // setting `T == int` works
for (T item in this) {
total += item;
}
return total;
}
}
And when I use my extension method with something like:
var addition = MyIterable([1, 2, 3]).sum();
I get this error:
type 'double' is not a subtype of type 'int'
identical(x, y) checks if x is the same object as y.
x == y checks whether x should be considered equal to y. The default implementation for operator == is the same as identical(), but operator == can be overridden to do deep equality checks (or in theory could be pathological and be implemented to do anything).
x is T checks whether x has type T. x is an object instance.
class MyClass {
MyClass(this.x);
int x;
#override
bool operator==(dynamic other) {
return runtimeType == other.runtimeType && x == other.x;
}
#override
int get hashCode => x.hashCode;
}
void main() {
var c1 = MyClass(42);
var c2 = MyClass(42);
var sameC = c1;
print(identical(c1, c2)); // Prints: false
print(identical(c1, sameC)); // Prints: true
print(c1 == c2); // Prints: true
print(c1 == sameC); // Prints: true
print(c1 is MyClass); // Prints: true
print(c1 is c1); // Illegal. The right-hand-side must be a type.
print(MyClass is MyClass); // Prints: false
}
Note the last case: MyClass is MyClass is false because the left-hand-side is a type, not an instance of MyClass. (MyClass is Type would be true, however.)
In your code, T is int is incorrect because both sides are types. You do want T == int in that case. Note that T == int would check for an exact type and would not be true if one is a derived type of the other (e.g. int == num would be false).
Basically, == is equality operator and "is" is the instanceof operator of Dart (If you come from Java background, if not, it basically tells you if something is of type something).
Use == for equality, when you want to check if two objects are equal. You can implement the == operator (method) in your class to define on what basis do you want to judge if two objects are equal.
Take this example:
class Car {
String model;
String brand;
Car(this.model, this.brand);
bool operator == (otherObj) {
return (otherObj is Car && other.brand == brand); //or however you want to check
//On the above line, we use "is" to check if otherObj is of type Car
}
}
Now you can check if two cars are "equal" based on the condition that you have defined.
void main() {
final Car micra = Car("Micra", "Nissan");
print(micra == Car("Micra", "Nissan")); // true
print(micra is Car("Micra", "Nissan")); // true
}
Hence, == is something you use to decide if two objects are equal, you can override and set it as per your expectations on how two objects should be considered equal.
On the other hand, "is" basically tells you if an instance is of type object (micra is of type Car here).
I trying make the following overloading inside my class:
class Array extends ListBase<double> {
List<double> l = [];
List<double> operator +=(List<double> b) {
var c = Array.length(l.length);
for(int i = 0; i < l.length; i++) {
c[i] = this[i] * b[i];
}
return c;
}
}
but the Dart compiler show the error message: the string '+=' ins't a user-definable operator. Is there some way to make the overloading of the operator += for others classes types?
Overload only operator +. Dart reuse operators that have a well known semantic meaning such as +=.
Add #override annotation if operator already defined in base class.
In C# I would implement Equals for a class with structural equality like this:
public override bool Equals(object obj)
{
if (this == obj)
{
return true;
}
var other = obj as MyType;
if (other != null)
{
return someField == other.someField &&
someOtherField == other.someOtherField;
}
return false;
}
In F# we have records for this, but if we want to use inheritance a type must be implemented.
What is the equivalent Equals implementation in F#?
As mentioned in the comments, you just need to override Equals. The compiler will also tell you that it is a good idea to override GetHashCode.
One neat trick is that you can just take all the relevant fields of your class, create tuples with them and then compare the tuples (or take hash code of the tuple). This makes the implementation much easier than if you were doing this by hand:
type Person(name:string, age:int) =
member x.Name = name
member x.Age = age
override x.GetHashCode() =
hash (name, age)
override x.Equals(b) =
match b with
| :? Person as p -> (name, age) = (p.Name, p.Age)
| _ -> false
Person("Joe", 42) = Person("Joe", 42)
I have a protocol:
protocol MasterGame {}
and a class that produces a singleton
class MasterGameImp : MasterGame {
static let sharedInstance = MasterGameImp()
}
Now I have another object that has a dependency on the protocol and has the property injected by it's instantiator.
class MyGameObject {
var masterGame: MasterGame?
}
I want to write a unit test to test that the singleton is injected properly into an instance of MyGameObject. What is the right way to do this? === does not accept arguments of type MasterGame and MasterGameImp. So apparently you can't check sameness that way between a protocol and a class. So I need another way to check sameness between the singleton and the stored property. Thanks!
The issue very much simplified is the following:
protocol P {
}
class X : P {
}
let x = X()
let p : P = x
print(x === p)
Binary operator === cannot be applied to operands of type 'X' and 'P'
print((x as P) === p)
Binary operator === cannot be applied to two 'P' operands
print(x === (p as! X))
true -> Working
What you have to do is upcast the protocol to its implementation, which es really not pretty at all :/
I did not find a better solution, it has something to do how swift handles protocols different than regular class inheritance. Changing to class P will result in all three above statements to succeed.
As #matt noted the code will of course crash if you incorrectly provide a wrong p which is not really a X. To solve that issue you should wrap the check into a if-condition:
if let xp = p as? X {
print(x === xp)
} else {
print("p is not of type X")
}
The following snippet of parser combinator demonstrates am aim of generalising binary comparison ops like > by using Ordered[T]. Gt seems to accomplish this at the AST level but I'm having trouble extending this concept.
The intGt parser works but is it possible to generalise this around Ordered[T] such that we don't need to write a second parser for floatGt (and hence one for all supported orderable types * all supported ops - no thanks).
object DSL extends JavaTokenParsers {
// AST
abstract class Expr[+T] { def eval: T }
case class Literal[T](t: T) extends Expr[T] { def eval = t }
case class Gt[T <% Ordered[T]](l: Expr[T], r: Expr[T]) extends Expr[Boolean] {
def eval = l.eval > r.eval // view-bound implicitly wraps eval result as Ordered[T]
}
// Parsers
lazy val intExpr: Parser[Expr[Int]] = wholeNumber ^^ { case x => Literal(x.toInt) }
lazy val floatExpr: Parser[Expr[Float]] = decimalNumber ^^ { case x => Literal(x.toFloat) }
lazy val intGt: Parser[Expr[Boolean]] = intExpr ~ (">" ~> intExpr) ^^ { case l ~ r => Gt(l, r) }
}
I tried playing around and this is the best I could come up with in the time I had:
import scala.util.parsing.combinator.JavaTokenParsers
object DSL extends JavaTokenParsers {
// AST
abstract class Expr[+T] { def eval: T }
case class Literal[T](t: T) extends Expr[T] { def eval = t }
case class BinOp[T,U](
val l : Expr[T],
val r : Expr[T],
val evalOp : (T, T) => U) extends Expr[U] {
def eval = evalOp(l.eval, r.eval)
}
case class OrderOp[O <% Ordered[O]](symbol : String, op : (O, O) => Boolean)
def gtOp[O <% Ordered[O]] = OrderOp[O](">", _ > _)
def gteOp[O <% Ordered[O]] = OrderOp[O](">=", _ >= _)
def ltOp[O <% Ordered[O]] = OrderOp[O]("<", _ < _)
def lteOp[O <% Ordered[O]] = OrderOp[O]("<=", _ <= _)
def eqOp[O <% Ordered[O]] = OrderOp[O]("==", _.compareTo(_) == 0)
def ops[O <% Ordered[O]] =
Seq(gtOp[O], gteOp[O], ltOp[O], lteOp[O], eqOp[O])
def orderExpr[O <% Ordered[O]](
subExpr : Parser[Expr[O]],
orderOp : OrderOp[O])
: Parser[Expr[Boolean]] =
subExpr ~ (orderOp.symbol ~> subExpr) ^^
{ case l ~ r => BinOp(l, r, orderOp.op) }
// Parsers
lazy val intExpr: Parser[Expr[Int]] =
wholeNumber ^^ { case x => Literal(x.toInt) }
lazy val floatExpr: Parser[Expr[Float]] =
decimalNumber ^^ { case x => Literal(x.toFloat) }
lazy val intOrderOps : Parser[Expr[Boolean]] =
ops[Int].map(orderExpr(intExpr, _)).reduce(_ | _)
lazy val floatOrderOps : Parser[Expr[Boolean]] =
ops[Float].map(orderExpr(floatExpr, _)).reduce(_ | _)
}
Essentially, I defined a small case class OrderOp that relates a string representing
an ordering operation to a function which will evaluate that operation. I then defined a function ops capable of creating a Seq[OrderOp] of all such ordering operations for a given Orderable type. These operations can then be turned into parsers using orderExpr, which takes the sub expression parser and the operation. This is mapped over all the ordering operations for your int and float types.
Some issues with this approach:
There is only one node type in the AST type hierarchy for all binary operations. This isn't a problem if all you are ever doing is evaluating, but if you ever wanted to do rewriting operations (eliminating obvious tautologies or contradictions, for instance) then there is insufficient information to do this with the current definition of BinOp.
I still needed to map orderExpr for each distinct type. There may be a way to fix this, but I ran out of time.
orderExpr expects the left and right subexpressions to be parsed with the same parser.