0

I am learning js inheritance and prototyping and my naming is probably totally off i am sorry for that.

i am trying to create a super object and prototype 2 sub object as properties and then inside one of the sub object call a function that is found in the other. it doesn't work for some reason.

UPDATE

my goal in here is: I am trying to make a small game - for fun and practice. My plan was to have 1 basic object called(object) that has positioning and other properties (that every other object will have) another object called(controls) for controls. Only objects that can move will have that object as well.

players are also objects and they will have both "object" and "controls". as their prototype.

Hope that cleared things a bit.

Code:

    // sub Object1
function object(){
    this.speed = 1;
    this.walkDistant = 5;

}

// sub Object2
function controls(){
    this.moveLeft = function(){
        console.log(this.speed , this.walkDistant);
        return this.speed * this.walkDistant;
    }
}

// super Object
function player(){
    // DoesNothing
}

player.prototype.object  = new object();
player.prototype.controls  = new controls();

var firstPlayer = new player();
console.log(firstPlayer.controls.moveLeft());

Or if you prefer fiddle : http://jsfiddle.net/rMaKa/1/

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Neta Meta
  • 4,001
  • 9
  • 42
  • 67

3 Answers3

1

Because a Player can be controlled you can mix in Controls with Player. Your object constructor function is a badly chosen name because a constructor function should start with a capital making it Object and you'd overwrite window.Object (bad idea). For this reason I've renamed it to Base. Player is a Base object and can be controlled so inherits from Base and has Controls mixed in.

For more information about constructor functions, mix ins, instance members and prototype check this link.

function Base() {
  this.speed = 1;
  this.walkDistant = 5;
}

// sub Object2
function Controls() {
}
Controls.prototype.moveLeft = function() {
  console.log(this.speed, this.walkDistant);
  return this.speed * this.walkDistant;
}

// super Object
function Player() {
  //make player have Base instance members
  Base.call(this);
  //make player heve Controls instance members
  Controls.call(this);
}
//player is a base object
Player.prototype = Object.create(Base.prototype);
//repair constrictor
Player.prototype.constructor = Player;
//Player can be controlled, copy controls prototype on player (mixin)
// this would be better suited in a helper function, see link posted in answer
var stuff;
for (stuff in Controls.prototype) {
  if (Controls.prototype.hasOwnProperty(stuff)) {
    Player.prototype[stuff] = Controls.prototype[stuff];
  }
}

var firstPlayer = new Player();

console.log(firstPlayer.moveLeft());

If you want the player to have controls you can try something like this:

function Controls(what) {
  //what do we need to control
  this.controlWhat=what;
}
Controls.prototype.moveLeft = function() {
  console.log(this.controlWhat.speed, this.controlWhat.walkDistant);
  return this.controlWhat.speed * this.controlWhat.walkDistant;
};

function Player() {
  this.speed = 1;
  this.walkDistant = 5;
  this.controls=new Controls(this);
}
var firstPlayer = new Player();

console.log(firstPlayer.controls.moveLeft());
Community
  • 1
  • 1
HMR
  • 37,593
  • 24
  • 91
  • 160
  • Thanks for the answer very much, mind explaining why did you do `Player.prototype.constructor = Player;` ? and why not just using new instead of `Player.prototype = Object.create(Base.prototype); //repair constrictor` ? – Neta Meta Jan 08 '14 at 02:35
  • The link I posted should answer both questions – HMR Jan 08 '14 at 07:03
  • yes it did, thanks very much seems things doesnt work exactly as i thought – Neta Meta Jan 08 '14 at 17:07
0

You can use Mixins to extend the functionality of an object using functionality already implemented in other objects. You could also have it that the sub-objects know about the super object as below.

function subClassA(containerClass) {
    this.containerClass = containerClass;
    this.methodA = function() {
        console.log(this.containerClass.b.methodB());
    }
}

function subClassB(containerClass) {
    this.containerClass = containerClass;
    this.methodB = function() {
        return 12345;
    }
}

function containerClass() {
    this.a = new subClassA(this);
    this.b = new subClassB(this);
}

var cc = new containerClass();
cc.a.methodA();

The Mixin approach would look something like this:

// extend function to add mixin support
function extend(destination, source) {
    for (var k in source) 
      if (source.hasOwnProperty(k))
        destination[k] = source[k];
    return destination;
}

function subClassA() { }
subClassA.prototype.methodA = function() {
    console.log(this.methodB());
};

function subClassB() { }
subClassB.prototype.methodB = function() {
    return 12345;
};

function superClass() {
    // ----------------
}

// add the subClassA and subClassB functionality
extend(superClass.prototype, subClassA.prototype);
extend(superClass.prototype, subClassB.prototype);

var sc = new superClass();
sc.methodA();
diolemo
  • 2,621
  • 2
  • 21
  • 28
  • yea I've done something like that before i was sure that there's a way to do it with prototype i mean both of the objects are under the same parent how comes they dont know of eachother ? – Neta Meta Jan 08 '14 at 00:02
  • @NetaMeta The shouldn't know about each other. It just doesn't work like that. – diolemo Jan 08 '14 at 00:04
  • @NetaMeta I have updated the answer to include a solution using Mixins. See if this is more suitable for you. – diolemo Jan 08 '14 at 00:17
  • Your mixin example would not work if you update subClassa.prototype after you've used it – Neta Meta Jan 09 '14 at 00:21
0

The problem is that you are trying to access a property that pertences to subObj1 from subObj2, but is the superObj that inherit both.

To achieve that, you should make your subObj1 inherit the subObj2.

// sub Object1
function name(){
    this.name = function(){
        var myName = 'FirstName';
        console.log(myName, this.last.lastName);
    }

    this.callName = function(){
        this.name();
    };
}

// sub Object2
function lastName(){
    this.lastName ='someLastName';
}

// super Object
function fullName(){
    // DoesNothing
}

name.prototype.last  = new lastName();
fullName.prototype.name  = new name();

var myName = new fullName();
myName.name.callName();

You can see this fiddle

Beterraba
  • 6,515
  • 1
  • 26
  • 33
  • This would add the lastName() functionality to all name() objects. If I understood correct I don't think that is wanted. – diolemo Jan 08 '14 at 00:10
  • i dont want sub object 1 and subobject 2 to be related, they are 2 separate objects, their only relation is through the super object. – Neta Meta Jan 08 '14 at 00:12
  • @NetaMeta Child object can access properties from their parents, but not from another childs. You should move your `moveLeft` method to your super class to achieve what you want (but that does not make sense either). I think that we have a problem related to the OO concept instead of JS specific. – Beterraba Jan 08 '14 at 00:15
  • what you mean related to the oo concept. what approach should i take instead? – Neta Meta Jan 08 '14 at 00:19
  • @NetaMeta You are on the right way, but I think that you should rethink your classes. `controls` is using information that exists on the `object` class, what seems, to me, that `controls` should inherit `object`. Or you can put this information on `player` or on `controls` itself. – Beterraba Jan 08 '14 at 00:24
  • The issue is player also need need object's properties not only conrtols also other class(physics) also need some of the properties, i am thinking maybe i should make my object as the super object while others extend it. – Neta Meta Jan 08 '14 at 00:28