public class Foo : Object {
	public int bar;

	[Semantics(overloads = "+")]
	public Foo add(Foo foo2) {
		var result = new Foo();
		result.bar = this.bar + foo2.bar;
		return result;
	}

	[Semantics(overloads = "-")]
	public Foo sub(Foo foo2) {
		var result = new Foo();
		result.bar = this.bar - foo2.bar;
		return result;
	}

	[Semantics(overloads = "*")]
	public Foo mult(Foo foo2) {
		var result = new Foo();
		result.bar = this.bar * foo2.bar;
		return result;
	}

	[Semantics(overloads = "/")]
	public Foo div(Foo foo2) {
		var result = new Foo();
		result.bar = this.bar / foo2.bar;
		return result;
	}
}

public interface Baz : Object {
	public abstract int bar { get; }
	
	[Semantics(overloads = "+")]
	public Baz add(Baz baz2) {
		return new FooBaz(this.bar + baz2.bar);
	}
}

public class FooBaz : Baz, Object {
	private int _bar;
	public int bar { get { return _bar; } }
	
	public FooBaz(int bar) {
		this._bar = bar;
	}
}

void main() {
	var foo1 = new Foo();
	foo1.bar = 6;
	var foo2 = new Foo();
	foo2.bar = 3;
	assert((foo1 + foo2).bar == 9);
	assert((foo1 - foo2).bar == 3);
	assert((foo1 * foo2).bar == 18);
	assert((foo1 / foo2).bar == 2);

	var fb1 = new FooBaz(6);
	var fb2 = new FooBaz(4);
	//Fails:
	//assert((fb1 + fb2).bar == 10);
	//Works:
	assert((((Baz) fb1) + ((Baz) fb2)).bar == 10);
}
