2014-10-04 38 views
1

這是Ruby書中實用面向對象設計的一個例子。我有興趣將這個ruby代碼翻譯成JavaScript,以便更好地理解JS中的duck-typing。任何人都可以幫助翻譯這段代碼來澄清如何最好的寫在Javascript中,或者至少幫助我開始?鴨子打字:使用鴨子打字將Ruby代碼翻譯成Javascript

此處的旅行類充當其他類(Mechanic,Trip_Coordinator,Driver)的接口。 Trip類中的準備方法使用Duck類型準備工具。

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?

+0

您可以使用Opal編譯器自動將其翻譯爲JavaScript:http://www.sitepoint.com/opal-ruby-browser-basics/ – 2014-10-04 01:42:14

+0

@AndersonGreen:代碼生成器如何幫助他們理解鴨子打字在JavaScript中? – 2014-10-04 02:26:34

+0

@ muistooshort如果這是一個學習練習,那麼最好手動翻譯它,當然。 – 2014-10-04 02:30:06

回答

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參數是在preparer的construstor中傳遞的。

+0

您認爲我提供的答案是最有效的解決方案嗎?每次我打電話給旅行時,程序員都必須知道哪些編寫者需要致電。你認爲最好是進一步重構這些代碼,以便只將計劃傳遞給Trip,Trip函數根據具體計劃決定哪些編寫者需要被調用?再次感謝您的幫助。 – JnL 2014-10-04 11:30:36

+0

我會考慮這一點。這取決於你想要什麼樣的設計。如果trip函數可以決定哪些編寫者不需要指定它們,那麼這可能會使調用代碼更簡單。 – fgb 2014-10-04 11:54:36