Duck打字:使用Duck打字将Ruby代码翻译成Javascript

时间:2014-10-04 01:38:03

标签: javascript ruby oop duck-typing

这是Ruby书中实用面向对象设计的一个例子。我有兴趣将这个ruby代码翻译成javascript,以便更好地理解JS中的duck-typing。任何人都可以帮助翻译此代码,以阐明如何最好地在Javascript中编写此代码或至少帮助我开始?

此处的旅程类充当其他类(Mechanic,Trip_Coordinator,Driver)的界面。 Trip类中的prepare方法使用Duck类型的preparer。

class Trip
    attr_reader :bicycles, :customers, :vehicle

    def prepare(preparers)
      preparers.each {|preparer|
         preparer.prepare_trip(self)}
    end
 end

class Mechanic
  def prepare_trip(trip)
    # Does something with trip.bicycles
  end
end


class Trip_Coordinator
  def prepare_trip(trip)
    # Does something with trip.customers
  end
end

class Driver
  def prepare_trip(trip)
    # Does something with trip.vehicle
  end
end

更新

我添加了一些代码,我相信这可能是上面Ruby代码的翻译。但是,当我运行代码时,我得到以下输出和错误:

mountain
2
jeep

/home/ubuntu/user/tests/trip.js:3
       preparer.prepare_trip(this)

TypeError: Object [object Object] has no method 'prepare_trip'

建议或建议将进一步提高对JS中鸭子类型的理解。

Javascript代码:

var Trip = function(preparers){
    return preparers.forEach(function(preparer){
       preparer.prepare_trip(this)
    }
)};

var Mechanic = function(trip){
    // does something with trip.bicycles                                                                                                                                                           
    prepare_trip: console.log(trip.bicycles);
};

var TripCoordinator = function(trip){
    //does something with trip.customers                                                                                                                                                           
    prepare_trip: console.log(trip.customers);
};

var Driver = function(trip){
    //does something with trip.vehicle                                                                                                                                                             
    prepare_trip: console.log(trip.vehicle);
};

// customer wants to go on a trip for two and needs a car                                                                                                                                          
var planA = {
    bicycles: "mountain",
    customers: 2,
    vehicle: "jeep"
};

//customer wants to go a trip for one and only ride a bike                                                                                                                                         
var planB = {
    bicycles: "road",
    customers: 1
};

Trip([new Mechanic(planA), new TripCoordinator(planA), new Driver(planA)]);
Trip([new Mechanic(planB), new TripCoordinator(planB)]);

更新2

根据下面fgb的解决方案和建议,我已经为下面的问题提供了最终解决方案。我添加了一个代理来消除调用者的依赖关系,他必须知道在创建旅行计划时他们需要做什么准备。

var Agent = function(plan){
    if("bicycles" && "customers" && "vehicle" in plan){
        Trip([new Mechanic(plan), new TripCoordinator(plan), new Driver(plan)]);
    }
    else if(!("vehicle" in plan) && "bicycles" && "customers" in plan){ //A driver is not needed                                                                                                                                        
        Trip([new Mechanic(plan), new TripCoordinator(plan)]);
    }
};

var Trip = function(preparers){
    return preparers.forEach(function(preparer){
       preparer.prepare_trip(this)
    }
)};
var Mechanic = function(trip){
    // does something with trip.bicycles                                                                                                                                                           
    this.prepare_trip = function() {
        console.log(trip.bicycles);
    }
};

var TripCoordinator = function(trip){
    //does something with trip.customers                                                                                                                                                           
    this.prepare_trip = function() {
        console.log(trip.customers);
    }
};

var Driver = function(trip){
    //does something with trip.vehicle                                                                                                                                                             
    this.prepare_trip = function() {
        console.log(trip.vehicle);
    }
};

// customer wants to go on a trip for two and needs a car                                                                                                                                          
var planA = {
    bicycles: "mountain",
    customers: 2,
    vehicle: "jeep"
};

//customer wants to go a trip for one and only ride a bike                                                                                                                                         
var planB = {
    bicycles: "road",
    customers: 1
};

Agent(planB);

相关SO讨论Example of Javascript Duck Typing?

1 个答案:

答案 0 :(得分:1)

代码几乎是正确的,但是你正在混淆构造函数和对象文字的语法。当你这样做时:

var Driver = function(trip){
    //does something with trip.vehicle                                                                                                                                                             
    prepare_trip: console.log(trip.vehicle);
};

'prepare_trip:'实际上是label,并没有定义对象的属性。

修复它的一种方法是:

var Driver = function(trip){
    //does something with trip.vehicle                                                                                                                                                             
    this.prepare_trip = function() {
        console.log(trip.vehicle);
    };
};

另请注意,代码与Ruby代码不完全相同:

preparer.prepare_trip(this);

这里,this是全局对象而不是trip对象,并且该方法中不使用该参数。在您的代码中,trip参数将在preparer的construstor中传递。