代码改变世界

函数重载库Overload

  Cat Chen  阅读(754)  评论(0编辑  收藏  举报
复制代码
(function() {
    Overload 
= {};

    
var copySignature = function(signature) {
        
var copy = [];
        
for (var i = 0; i < signature.length; i++{
            copy.push(signature[i]);
        }

        
if (signature.arguments) {
            copy.arguments 
= true;
        }

        
return copy;
    }
;
    
    
var inheritanceComparator = function(type1, type2) {
        
if (type1 == type2) {
            
return 0;
        }
 else if (type2 == Overload.Any) {
            
return 1;
        }
 else if (type1 == Overload.Any) {
            
return -1;
        }
 else if (type1.prototype instanceof type2) {
            
return 1;
        }
 else if (type2.prototype instanceof type1) {
            
return -1;
        }
 else {
            
return 0;
        }

    }
;
    
    
var overloadComparator = function(overload1, overload2) {
        
var signature1Better = false;
        
var signature2Better = false;
        
var signature1 = overload1.signature;
        
var signature2 = overload2.signature;
        
if (!signature1.more && signature2.more) {
            signature1Better 
= true;
            signature1 
= copySignature(signature1);
            signature1.length 
= signature2.length;
        }
 else if (signature1.more && !signature2.more) {
            signature2Better 
= true;
            signature2 
= copySignature(signature2);
            signature2.length 
= signature1.length;
        }
 else if(signature1.more && signature2.more) {
            
if (signature1.length > signature2.length) {
                signature2 
= copySignature(signature2);
                
while (signature2.length < signature1.length) {
                    signature2[signature2.length] 
= Overload.Any;
                }

            }
 else if (signature1.length < signature2.length) {
                signature1 
= copySignature(signature1);
                
while (signature1.length < signature2.length) {
                    signature1[signature1.length] 
= Overload.Any;
                }

            }

        }

        
for (var i = 0; i < signature1.length; i++{
            
var comparison = inheritanceComparator(signature1[i], signature2[i]);
            
if (comparison > 0{
                signature1Better 
= true;
            }
 else if (comparison < 0{
                signature2Better 
= true;
            }

        }

        
if (signature1Better && !signature2Better) {
            
return 1;
        }
 else if (!signature1Better && signature2Better) {
            
return -1;
        }
 else {
            
return 0;
        }

    }
;
    
    
var matchSignature = function(argumentsArray, signature) {
        
if (argumentsArray.length < signature.length) {
            
return false;
        }
 else if (argumentsArray.length > signature.length && !signature.more) {
            
return false;
        }

        
for (var i = 0; i < signature.length; i++{
            
if (!(signature[i] == Overload.Any
                
|| argumentsArray[i] instanceof signature[i]
                
|| argumentsArray[i].constructor == signature[i])) {
                    
return false;
            }

        }

        
return true;
    }
;
    
    Overload.create 
= function(overloadsArray) {
        
var overloads = [];
        
        
var select = function(argumentsArray) {
            
var matches = [];
            
for (var i = 0; i < overloads.length; i++{
                
if (matchSignature(argumentsArray, overloads[i].signature)) {
                    matches.push(overloads[i]);
                }

            }

            
switch (matches.length) {
                
case 0:
                    
return null;
                
case 1:
                    
return matches[0]["function"];
                
default:
                    matches 
= matches.sort(overloadComparator);
                    
if (overloadComparator(matches[matches.length - 1], matches[matches.length - 2]) > 0{
                        
return matches[matches.length - 1]["function"];
                    }
 else {
                        
return null;
                    }

            }

        }
;
        
        
var overloaded = function() {
            
var overload = select(arguments);
            
if (overload) {
                
return overload.apply(this, arguments);
            }
 else {
                
throw "cannot select a proper overload";
            }

        }
;
        
        overloaded.select 
= select;
        
        overloaded.add 
= function(signature, overload) {
            
if (signature instanceof Array) {
                signature 
= copySignature(signature);
            }
 else if (signature.constructor == String) {
                
if (signature.replace(/(^\s+|\s+$)/ig, ""== ""{
                    signature 
= [];
                }
 else {
                    signature 
= signature.split(",");
                    
for (var i = 0; i < signature.length; i++{
                        
var typeExpression = signature[i].replace(/(^\s+|\s+$)/ig, "");
                        
var type = null;
                        
if (typeExpression == "*"{
                            type 
= Overload.Any;
                        }
 else if (typeExpression == "..."{
                            type 
= Overload.More;
                        }
 else {
                            
try {
                                type 
= eval("(" + typeExpression + ")");
                            }
 catch (error) {
                                
throw "type expression cannot be evaluated: " + typeExpression;
                            }

                        }

                        signature[i] 
= type;
                    }

                }

            }
 else {
                
throw "signature is neither a string nor an array";
            }

            
for (var i = 0; i < signature.length; i++{
                
if (!(signature[i] instanceof Function)) {
                    
throw "argument type should be a function";
                }

                
if (i < signature.length - 1 && signature[i] == Overload.More) {
                    
throw "arguments type cannot be used in any argument except the last one";
                }

            }

            
if (signature[signature.length - 1== Overload.More) {
                signature.length 
= signature.length - 1;
                signature.more 
= true;
            }

            overloads.push(
{
                
"signature": signature,
                
"function": overload
            }
);
            
return this;
        }
;
        
        
return overloaded;
    }
;
    
    Overload.add 
= function(signature, overload) {
        
return Overload.create().add(signature, overload);
    }
;
    
    Overload.Any 
= function any() {
        
throw "this type is only an identifier and should not be instantiated"
    }
;

    Overload.More 
= function more() {
        
throw "this type is only an identifier and should not be instantiated"
    }
;
}
)();
复制代码
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示