Repository navigation
Function Overloading
在同一个脚本里,可以有多个同名但参数不同的函数。这叫重载。例如:
A script may contain several functions with the same name but different parameters. This is overloading:
int max(int a, int b) {
if (a > b) return a;
return b;
}
double max(double a, double b) {
if (a > b) return a;
return b;
}
两个 max 名字相同,一个接收两个 int,一个接收两个 double。调用时,HimDSL 会根据参数类型和个数选择合适的那一个。
Both are named max; one takes two ints, the other two doubles. When you call it, HimDSL selects the version matching the argument types and count.
函数能否重载,取决于参数列表,与返回类型无关。
Whether two functions overload depends on the parameter list, not the return type.
可以重载:
May overload:
int f(int x) { return x; }
int f(int x, int y) { return x + y; } // 参数个数不同
string f(string s) { return s; } // 参数类型不同
不能重载(参数列表完全相同):
Cannot overload (identical parameter lists):
int f(int x) { return x; }
double f(int x) { return x * 1.0; } // ✗ 报错:与上一个签名重复
即使返回类型不同,只要参数列表一致,就算重复定义,会报错。返回类型不参与重载判断。
Even with different return types, identical parameter lists count as duplicates and error. Return types do not distinguish overloads.
调用重载函数时,HimDSL 按下面的顺序选择:
When calling an overloaded function, HimDSL chooses in this order:
-
参数个数。
-
参数类型。
-
有具体类型声明的优先。
-
Argument count.
-
Argument types.
-
Functions with declared types beat untyped ones.
最常见的用法是通过参数类型区分:
The most common form distinguishes by argument types:
string describe(int n) { return "整数 " + n; }
string describe(string s) { return "字符串 " + s; }
string describe(double d) { return "小数 " + d; }
int main() {
runcmd("CONSOLE", "say " + describe(42)); // 整数 42
runcmd("CONSOLE", "say " + describe("hello")); // 字符串 hello
runcmd("CONSOLE", "say " + describe(3.14)); // 小数 3.14
}
每次调用都根据实参类型选到相应的版本。
Each call selects the matching version by argument type.
如果参数个数不同,HimDSL 会先按个数缩小范围,再按类型选择:
When counts differ, HimDSL narrows by count first, then by type:
int add(int a, int b) { return a + b; }
int add(int a, int b, int c) { return a + b + c; }
int main() {
add(1, 2); // 调用第一个
add(1, 2, 3); // 调用第二个
}
参数个数完全不匹配的调用不会自动补齐或截断,而是报错。
A call whose count matches no overload does not auto-pad or truncate; it errors.
类型匹配不是严格相等,而是能否转换。例如整数可以传进期望 double 的参数:
Type matching is not strict equality but convertibility. For example, an integer may pass where a double is expected:
double half(double x) { return x / 2.0; }
int main() {
double a = half(5); // 5 被视为 5.0
double b = half(5.0);
}
反过来,double 传给 int 参数不会自动转换,需要在调用处手动 toInt:
Conversely, a double passed to an int parameter is not auto-converted; call toInt explicitly:
int negate(int x) { return -x; }
int main() {
int a = negate(5); // ✓
int b = negate(toInt(5.5)); // ✓ 显式转换
int c = negate(5.5); // ✗ 类型不匹配
}
这种"只宽不窄"的规则能帮你避免意外丢失精度。
This "widen only" rule prevents accidental precision loss.
当两个重载同样匹配一个调用时,HimDSL 会报"重载歧义"错误,而不是随便挑一个。例如:
When two overloads match a call equally well, HimDSL raises an "ambiguous overload" error instead of picking one arbitrarily:
int f(int x, int y) { return x + y; }
double f(double x, int y) { return x + y; }
int main() {
f(1, 2); // 两个都能接受,报歧义
}
修复方式是显式转换实参,让其中一个候选明确胜出:
Fix by explicitly converting the arguments so one candidate wins:
f(1.0, 2); // 明确选第二个
或者干脆不要写这种易混的重载。
Or simply avoid such easily-confused overloads.
经验法则:重载只用来区分明显不同的情况。例如参数类型不同、参数个数不同。两个重载如果只差一个类型,而调用者很难一眼看出选哪个,就应该换个名字。
Rule of thumb: overload only to distinguish clearly different cases. If two overloads differ by a single type and the caller cannot tell which will be chosen, rename one.
HimDSL 没有默认参数。想要"可选参数"的效果,只能写多个重载,最短的那个调用最长的那个:
HimDSL has no default parameters. To fake optional arguments, write several overloads where the shortest delegates to the longest:
string tag(string text) {
return tag(text, "info");
}
string tag(string text, string level) {
return "[" + level + "] " + text;
}
int main() {
runcmd("CONSOLE", "say " + tag("启动完成")); // [info] 启动完成
runcmd("CONSOLE", "say " + tag("有异常", "warn")); // [warn] 有异常
}
这就是 Java 里常见的写法。每个重载做一件小事,最短的调用最长的。
This is common in Java. Each overload does one small thing; the shortest delegates to the longest.
重载不是越多越好。如果两个函数做的事明显不同,就不要用同名。例如:
Overloading is not about count. If two functions do clearly different things, do not share a name:
// ✗ 名同,语义不同,读起来很累
void send(string msg) { /* 发广播 */ }
void send(player p, string msg) { /* 给玩家发私信 */ }
// ✓ 换名字
void broadcast(string msg) { /* 发广播 */ }
void tell(player p, string msg) { /* 给玩家发私信 */ }
重载适合"同一个操作针对不同数据"(例如 max 对 int 和 double),而不是"完全不同的两个操作"。
Overload for "same operation on different data" (like max for int and double), not for "two different operations".
-
重载 = 同名、参数列表不同。
-
返回类型不参与判断。
-
解析顺序:个数 → 类型 → 有类型声明的优先。
-
类型匹配是"只宽不窄"。
-
歧义会报错,需要显式转换。
-
没有默认参数,用重载模拟。
-
语义不同的操作别重载。
-
Overloading = same name, different parameter lists.
-
Return type does not count.
-
Resolution: count → type → declared-type preference.
-
Type matching is "widen only".
-
Ambiguity errors; convert explicitly.
-
No default parameters; simulate with overloads.
-
Do not overload semantically different operations.
下一章 [Lambda 表达式 / Lambda Expressions] 介绍一种把"代码块"当值传递的写法,GUI 回调、事件处理器都会用到。
Next, [Lambda 表达式 / Lambda Expressions] introduces passing a code block as a value — used by GUI callbacks and event handlers.
- 首页 / Home
- 安装与快速开始 / Installation & Quick Start
- 第一个脚本 / Your First Script
- 命令速查 / Command Reference
- 自动执行脚本 / Auto-run Scripts
- 定义函数 / Defining Functions
- 函数重载 / Function Overloading
- Lambda 表达式 / Lambda Expressions
- 函数式接口 / Functional Interfaces
- 选择器总览 / Selectors Overview
- 选择器过滤器 / Selector Filters
- EntityRef 引用 / EntityRef
- 占位符参考 / Placeholders Reference
- PlaceholderAPI 桥接 / PAPI Bridge
- 创建 GUI / Creating a GUI
- GUISlot 槽位 / GUISlot
- 点击回调 / Click Callbacks
- onClose 回调 / onClose Callback
- GUI 刷新 / GUI Refresh
- 数学函数 / Math Built-ins
- 高精度计算 / BigDecimal Built-ins
- 字符串函数 / String Built-ins
- 集合函数 / Collection Built-ins
- 文件 I/O / File I/O
- 命令与 sleep / Commands & sleep