Forums

Whats wrong with my code?

General discussion about Cobra. Releases and general news will also be posted here.
Feel free to ask questions or just say "Hello".

Whats wrong with my code?

Postby snakeman » Sat Dec 14, 2013 8:02 am

Hi all,

still new to cobra, i have difficulties with inheritance. I want an abstract class BoxOrPoint from which i want to inherit Box and Point. Box should get additional methods that are not present at BoxOrPoint. So this is my code so far
class BoxOrPoint is abstract
var _location as List<of number>

cue init(location as List<of number>)
base.init
assert location.count == 3
_location = location

get location from var

def centerOfMass as List<of number> is abstract
def totalMass as number is abstract

class Point inherits BoxOrPoint
var _mass as number
cue init(location as List<of number>, mass as number)
base.init(location)
_mass = mass

def centerOfMass as List<of number>
return base.location

def totalMass as number
return _mass


The compiler tells me that an error occures at line 24 because
Code: Select all
Member "totalMass" also exists in the base class. YOu must specify "is override" or "is new", or change the name
. But why? I'm just implementing abstract methods and it works this way with centerOfMass, but not with totalMass.

When i add an "is new" modifier to the def totalMass, the compiler tells me that Point does not implement the inherited abstract member BoxOrPoint.TotalMass().

Any suggestions how to fix this code?

Thanks!
snakeman
 
Posts: 7

Re: Whats wrong with my code?

Postby nerdzero » Sat Dec 14, 2013 12:54 pm

Since those functions exist in the base class and you are overriding them in the subclass, you need to add "is override" like this:
def centerOfMass as List<of number> is override
return base.location

def totalMass as number is override
return _mass

Also, in "centerOfMass", you probably want just "return .location" instead of "return base.location". Since you are not overriding "location" in the subclass, the implementation in the base class will automatically be called. You could also just do "return _location" since "_location" is a protected variable and is visible to the subclass.
nerdzero
 
Posts: 286
Location: Chicago, IL

Re: Whats wrong with my code?

Postby Charles » Sat Dec 14, 2013 1:23 pm

nerdzero is correct. Also, Cobra allows you to skip "is override" if you have a "base" call in the method. The idea is that either one of those shows that the programmer understands that a method is being overridden. What I didn't anticipate is a base call to a different member, which is fairly rare. So I will tighten that up after the next release.

I have thought about blocking base calls to other members in general because it's almost never needed. But then I do use it about once every two years to get out of some jam...
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Whats wrong with my code?

Postby Charles » Sat Dec 14, 2013 2:05 pm

In terms of object oriented design, I notice that there is a List<of number> for which there is at least one expectation: it has to have 3 elements exactly. I presume this is a conceptual point in space without mass. I would break that out into a class to be used by the other objects. Here is my take on things:

http://pastebin.com/NDeMSFez

Hmm, looks a bit funny with the extra wide tabs and the Python highlighting. But still readable, and of course you can download it.

Feel free to use anything there.

If you do something interesting, like colliding objects, spinning, etc. feel free to share back. Could become an example program.
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Whats wrong with my code?

Postby kobi7 » Sun Dec 15, 2013 4:13 am

Hi, perhaps a newbie question, but what is the advantage of an abstract class, over interfaces and mixins (or extension methods for that matter)?
does a language that have mixins be able to remove the abstract feature?
you can only inherit from one abstract, but can inherit from multiple interfaces.

What am I missing?

thanks
Falun Dafa is Good.
Truth, Compassion, Forbearance is Good.
kobi7
 
Posts: 82
Location: Israel

Re: Whats wrong with my code?

Postby Charles » Sun Dec 15, 2013 12:06 pm

Compared to a pure interface, an abstract class can provide implementations of methods that act as the default implementations until/unless you override them. Also, they can provide member variables. Also, in Cobra you can inherit the initializers/constructors of your base class if you don't specify any of your own. So that can be convenient as well.

Mix-ins are a possibility, but they involve code injection, and especially across library boundaries that may be a disadvantage.

Typically, I will use a combination of base classes, interfaces and mix-ins.

But feel free to explore different approaches and reach your own conclusions. Maybe this conversation will evolve.
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Whats wrong with my code?

Postby snakeman » Mon Dec 16, 2013 2:47 pm

Thanks for your replies! It worked the way nerdzero explained. Good to know!

So here's the long story about last saturday: I dealt with the barnes-hut algorithm and tried to implement the build algorithm in cobra. It was a lot of fun for me, but actually it doesn't really make use of interfaces or abstract methods. The code is not testet so far (at least it compiles) and the propability that i continue on it is very little (unless someone gives me some suggestions).

But i decided to post it anyway. At the moment i believe that the code could look much better if cobra had numpy arrays. For this it would be neccessary to allow overloading of arithmetic operators.

class Config
const MAXPOINTS = 1
const DIMENSIONS = 3


class Vector inherits List<of number>
test
v = Vector([1.0,2.0,3.0])
w = Vector([9.0,8.0,7.0])
assert v.add(w) == Vector([10.0, 10.0, 10.0])
assert v.multiply(2) == Vector([2.0, 4.0, 6.0])

cue init
base.init(Config.DIMENSIONS)
for i in Config.DIMENSIONS, base.add(0)

cue init(location as List<of number>)
require location.count == Config.DIMENSIONS
base.init
for x in location, base.add(x)

def multiply(factor as number) as Vector
return Vector(for x in this get x*factor)

def divide(quotient as number) as Vector
return Vector(for x in this get x/quotient)

def add(v as Vector) as Vector
return Vector(for i in v.count get this[i]+v[i])

def addHere(v as Vector)
for i in .count, this[i] += v[i]


interface IMatter
def com as Vector
def mass as number


class Point implements IMatter
var _mass as number
var _location as Vector

cue init(location as Vector, mass as number)
base.init
_location = location
_mass = mass

def com as Vector
return _location

def mass as number
return _mass


class Box implements IMatter

var _location as Vector # center of our cubic box
var _fel as number # the Fourths of the cube's Edge Length
var _isDivided as bool # becomes true if this box is split into subboxes
var _points as List<of Point> # holds points unlelss _isDivided
var _subBoxes as List<of Box> # holds boxes if _isDivided
var _mass as number # sum of all masses in this cube
var _comTimesMass as Vector # center-of-mass times total mass

cue init(location as Vector, fel as number)
base.init
_location = location
_fel = fel
_isDivided = false
_points = List<of Point>()
_subBoxes = List<of Box>()
_mass = 0
_comTimesMass = Vector()

def subBoxFor(vec as Vector) as Box is protected
key = 0
for i in Config.DIMENSIONS
if vec[i] > _location[i]
key += 2^i # 2 is a basis for all natural numbers
return _subBoxes[key]

def ctrForSubbox(key as int) as Vector is protected
ctr = Vector(_location)
for i in Config.DIMENSIONS-1:-1:-1
ctr[i] += _fel * if(key < 2**i, -1, 1)
key -= 2**i
return ctr

def split is protected
eel = _fel/2 # eigths of the edge lengths
for key in 2**Config.DIMENSIONS
_subBoxes.add(Box(.ctrForSubbox(key), eel))
for p in _points
.subBoxFor(p.com).add(p)
_points.clear
_isDivided = true

def add(p as Point)
_mass += p.mass
_comTimesMass.addHere( p.com.multiply(p.mass) ) # could also read: _comTimesMass += p.com * p.mass

if ( not _isDivided ) and ( _points.count >= Config.MAXPOINTS )
.split

branch _isDivided
on false, _points.add(p)
on true, .subBoxFor(p.com).add(p)

def mass as number
return _mass

def com as Vector
return _comTimesMass.divide(_mass) # this could read: return _comTimesMass / _mass
snakeman
 
Posts: 7

Re: Whats wrong with my code?

Postby Charles » Mon Dec 16, 2013 3:29 pm

When you mentioned numpy arrays, I couldn't tell if you meant that you just wanted the operator overloads or if you wanted other things like multiple dimensions. If you wanted the extra dimensions, we have MultiList which is built into the standard library:

http://cobra-language.com/trac/cobra/br ... List.cobra

Regarding suggestions, your Box class has no "test" section and there is no "def main". Either of those could be a next step towards getting this to do something.
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Whats wrong with my code?

Postby snakeman » Mon Dec 16, 2013 3:36 pm

Of course i'm happy that multilists have found their way into cobra!
But the operator overloads are to me the most "impressing" thing about numpy arrays. I know this is kinda trivial (if operator overloading is supported), but after using it a couple of times i found myself so happy and really enjoyed that clean look of my code.
snakeman
 
Posts: 7

Re: Whats wrong with my code?

Postby Charles » Tue Dec 17, 2013 3:05 am

If you get your program working in both languages, it would be interesting to compare their performance. I know with NumPy, the actually arrays are fast, but the Python interpreted code is still slow.

If you time something with Cobra, use "cobra -c -turbo ..." where -turbo will turn off some run-time checks that slow things down. The closest thing in Python is -o
Charles
 
Posts: 2515
Location: Los Angeles, CA


Return to Discussion

Who is online

Users browsing this forum: No registered users and 33 guests