Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CoffeeScript: Accessing outer class objects from inner class instance

Tags:

coffeescript

If there any way to access outer class fields from inner class instance, EXCEPT passing outer class instance to inner class constructor?

To be more specific, I have a simple example:

class Test
  constructor: (@number) ->

  class SubTest
    constructor: (@name) ->

    toString: () ->
      console.log @name, @number

  getSubTest: () ->
    return new SubTest "SubTest"

test = new Test 10
test.getSubTest().toString() # SubTest undefined

So, I want to get "SubTest 10" instead of "SubTest undefined". Is it possible?

like image 584
Mariya Davydova Avatar asked Aug 27 '12 11:08

Mariya Davydova


People also ask

How do you access the outer class variable from the inner class?

If you want your inner class to access outer class instance variables then in the constructor for the inner class, include an argument that is a reference to the outer class instance. The outer class invokes the inner class constructor passing this as that argument.

Can inner class access outer class method?

Method Local inner classes can't use a local variable of the outer method until that local variable is not declared as final. For example, the following code generates a compiler error.

Can inner class access outer class private variables C#?

You need to pass in the parent (since there's no outer keyword), but the inner class can access private members of the parent.

Can static inner class access outer class variables?

Unlike inner class, a static nested class cannot access the member variables of the outer class. It is because the static nested class doesn't require you to create an instance of the outer class.


Video Answer


2 Answers

Good news! It turns out if you create the closure over @ yourself, it works just fine:

class Test
  self = []
  constructor: (@number) ->
    self = @

  class SubTest
    constructor: (@name) ->

    toString: () ->
      @name + self.number

  getSubTest: () ->
    return new SubTest "SubTest"

test = new Test 10
v = test.getSubTest().toString()

alert v

Translates to :

var Test, test, v;

Test = (function() {
  var SubTest, self;

  self = [];

  function Test(number) {
    this.number = number;
    self = this;
  }

  SubTest = (function() {

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

    SubTest.prototype.toString = function() {
      return this.name + self.number;
    };

    return SubTest;

  })();

  Test.prototype.getSubTest = function() {
    return new SubTest("SubTest");
  };

  return Test;

})();

test = new Test(10);

v = test.getSubTest().toString();

alert(v);

Output:

SubTest10

like image 122
asawyer Avatar answered Oct 28 '22 12:10

asawyer


It's an old question but the accepted answer doesn't work if multiple instances of the outer class are needed (as pointed out by @costa-shapiro). Here is an alternative approach to create the closure with the inner class.

SubTest = (test) ->
  class SubTest
    constructor: (@name) ->

    toString: () =>
      console.log @name, test.number

class Test
  constructor: (@number) ->
    @SubTest = SubTest @

  getSubTest: () =>
    return new @SubTest "SubTest"

test = new Test 10
test.getSubTest().toString()
like image 38
pghalliday Avatar answered Oct 28 '22 14:10

pghalliday