有什么方法可以实现像在kotlin中覆盖运算符的东西吗?

时间:2018-03-14 09:01:33

标签: kotlin

最近,我正在使用kotlin中的列表,并有以下代码段:

a = listOf(1, 2, 3, 4)
println(a[-2])

当然这会导致IndexOutOfBoundsException所以我认为扩展此功能会很好。所以我认为可以覆盖get类中的List运算符:

operator fun <T> List<T>.get(index: Int): T =
        // Here this should call the non-overridden version of
        // get. 
        get(index % size)

我理解扩展只是静态方法,因此不能被覆盖,但有没有办法可以实现这样的东西?

当然你可以创建另一个功能

fun <T> List<T>.safeGet(index: Int): T = get(index % size)

但我想知道是否还有其他方式。

(我知道index % size是一种非常天真的方式来做我想做的事情,但它不是我的问题的焦点,并使代码更小。) < / p>

修改

当我写这个问题时,我认为%运算符会在右侧为正数时返回正数 - 就像在python中一样。我在这里保留原始问题只是为了保持一致。

2 个答案:

答案 0 :(得分:2)

你正在尝试一些不可能的事情,因为扩展程序总是被成员遮蔽,即使@JvmName也无法拯救你。

解决方法:使用您的第二个解决方案,或添加一个丑陋的Unit参数(看起来像a[x, Unit]),但可以与自己的get方法一起存在。

另一种解决方案:创建自己的List实施(推荐)。

答案 1 :(得分:2)

由于get已经在List中定义了get运算符,因此您无法重新定义Int(带有一个invoke参数)。 但是,您可以覆盖List中未定义的fun main(args: Array<String>) { val a = listOf(1, 2, 3, 4) println(a(-2)) } // If `index` is negative, `index % size` will be non-positive by the definition of `rem` operator. operator fun <T> List<T>.invoke(index: Int): T = if (index >= 0) get(index % size) else get((-index) % (-size)) 运算符。

List

虽然我认为使用适当的名称为(positive value) % (negative value)创建新的扩展方法将是更好的选择。

作为旁注,(negative value) % (positive value)为非负数,%为非正数。 在以下示例中,Kotlin中的rem对应于Haskell中的public class Startup: IStartup { protected IServiceProvider _provider; private readonly IConfiguration _configuration; public Startup(IConfiguration configuration) => _configuration = configuration; // This method gets called by the runtime. Use this method to add services to the container. public IServiceProvider ConfigureServices(IServiceCollection services) { services.Configure<MvcOptions>(options => options.Filters.Add(new RequireHttpsAttribute())); SetUpDataBase(services); services.AddMvc(); services .AddIdentityCore<User>(null) .AddDefaultTokenProviders(); return services.BuildServiceProvider(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app) { var options = new RewriteOptions().AddRedirectToHttps(); app.UseRewriter(options); app.UseAuthentication(); app.UseMvc(); using(var scope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope()) { var context = scope.ServiceProvider.GetService<DatabaseContext>(); EnsureDatabaseCreated(context); } } protected virtual void SetUpDataBase(IServiceCollection services) => services.AddDbContext(_configuration); protected virtual void EnsureDatabaseCreated(DatabaseContext dbContext) { dbContext.Database.Migrate(); } } https://stackoverflow.com/a/28027235/869330