“20S的面向对象语言”

2021-03-13 23:17:09

面向对象的编程现在是不合适的,它已经有一段时间了。很少是有意地对象面向对象的新编程语言。和本身的理由是:OO经常需要大量的样板,它迫使到不自然的对象层次结构,并鼓励隐藏的变形状态。

但是,如果我们在2021年从头开始划痕,java或c#中的某些东西,就可以了解我们的一切'从函数的编程和十年加上了小组的oo批评,我们可以修复吗?特别是如果我们没有对遗留代码兼容的期望?

以下是我,个人,在新的Oolanguage中想要的一些不太明显的选择:

所有这些中的常见因素都是纯粹oo(不是" multiparadigm"),但将功能特征合并到其类型系统中以oo的方式缩短它们。

Scala现在一直是我最喜欢的编程语言。 ITGES非常接近我理想的OO和功能概念。但是ScaMa' Smain问题是,它有十几种方法可以做到所有事情:Java类,代数数据类型,独立函数,含义和一切偶联。

像几乎所有替代的JVM语言一样,Scala逃脱了王国,并且蔑视Java'要求一切都属于一个课程。事实上,Scala在实用性和功能规划的名称中蔑视几件OO正统。

但也许我们' VE对名词王国不公平。 java' s语法并不是#39; tforbid动词,它只是强制一个一致的词序,首先是名词始终如一的。而这有一个主要优势:IDE和文档Discoverability。

当一切都是类的成员时,每个非局部方法调用都会达到点点,这意味着每个非本种方法调用都可以自动下拉列表。 IDE中可以在IDE中探讨Java API,仅使用下拉列表和Popup文档。我们可以提供扩展方法(如C#)来处理现有类型的新操作,因此实用程序函数不应' t浮动围绕实用程序类或静态方法。

继承人得到了一个糟糕的说唱。不可否认,有一些原因:大多数时间,当你扩展超类时,你真正想要的是一个方向性某种组成。

但是,一旦我们决定一切都是一个对象和每个函数都属于一个对象,每个形式的代码重用都开始继承:Mixins,特征,具有默认方法的接口,具有代理方法的组成等.and,随着OO语言开发新功能,这些倾向于除名字中的多种子势。为什么不接受它?

继承问题(可以说)一个心理模型问题,而不是语言曲目。接口是类的子集。有时需要连接界面脚趾贴图,以强制使用类型系统可以' t描述的不变性。是 - 一个关系很有用(请参阅:CollectionSlibraries),但是该线通常在错误的地方绘制。脆弱的BaseClasses只是一个有意识地避免的防模式,您可以在TypSeclasses或接口上使用默认方法进行同样的错误。

多重继承解决了Java类层次结构中的大多数过度思考和BikesheddingInvolved。在具有Sane的语言中,继承看起来更像是作文:只是选择你想要的功能并将其粘合在一起。层次结构是一个DAG,Nota树。一旦你有多种继承,你就不需要接口,因为那里的界面和#39;界面与抽象类之间不再区别。

那么你如何解决名字碰撞?只需制作方法和字段就是合格的。如果foo扩展栏和baz,这两者都定义了方法qux,您可以通过foo.bar \ qux或foo.baz \ qux在实例foo上引用任何方法.baz \ qux。 i' m使用backslash作为命名空间分隔符,因为它'幻像/但尚未用作分割符号。

安全演员也可以解决一些名称碰撞。如果栏和baz展开QUX,并且方法期望QUX参数,FOO可以作为BAR或FOO作为BAZ传递。

A类{foo(){print(" a")} b级扩展了一个{foo(){print(" b")} class c扩展了一个{foo() {打印(" c")} d级d延伸b& C

假设您有一个静态类型A的对象。它' s的一个例子,但编译器不知道。如果你打电话给foo(),会发生什么?您可以在编译时' Tdisambigate,因为你不知道它和#39;'是B或C的一个例子。

最简单的方法是从kotlin获取页面,并要求d覆盖foo anddisamiguate。

Scala使用保留单词来自动化常见模式:密封,案例类,对象。您可以在没有这些关键词的情况下制作单例对象或总和类型,就像您可以在Java中,但编译器赢得了' T知道你和#39;重做。为什么可以创建这些二等公民类型?

这就是我认为OO代数数据类型可以看起来像,在我的实验中,但更好的语法:

类地址{new(this.state:string,this.city:string,this.street:string,this.zip:int)}类列表(t){private new()head:选项(t)尾部:选项( list(t))静态类nil扩展列表(nothes){静态self = new()head = none = none = self xont.self}静态(t)class缺点扩展列表(t){private(list)new(私有this.car:t,private .cdr:list(t))head = some.new(car)tail = some.new(cdr)}静态nil = nil.self静态(t)alias cons = cons \ new}

此示例包含产品类型,SUM类型,带有双方字段的抽象类,以及单例对象。但它没有使用摘要,密封,案例类或对象的单词。没有bodyis摘要的领域或方法。带有任何抽象成员的类,或受保护的构造函数,isAbstract。具有私有构造函数和静态内部子类的类,所有这些都具有私有构造函数,是一种密封的总和类型。一个静态自我属性(这是一个神奇的关键字,Can' t完全逃脱)是单身,并意味着私有构造函数。

编译器只要在看到它们时应该知道这些模式。他们不需要额外的关键字。错误消息应该是信息的足够困境,在用户意外地制作了一类摘要,或者是完全密封的makea类。

大写是重要的,这意味着它在Haskell中所做的一切:IFIT以大写字母开头,它' s类型。

泛型刚刚使用括号,而不是<>或者 []。因为课程被大写化所作,这是明确的。通用方法可以释放括号套,因为与Scala不同,没有Currying。

泛化是refied(如c#,与Java不同)。所以静态有时必须用类型参数缩小,知道它是否' s静态到列表或列表(t)。列表(a).nil和list(b).nil是相同的类,但列表(a).cons和list(b).cons是不同的。

这些是键入其自身类型的参数,如t(_)。我知道这一切的语言支持OO类和HKT是Scala,Butit' s一个奇怪的情况。 Scala是ML用螺栓固定在侧面的Java。如果您想要在Scala中函数的事物,您最终可以在替代职能宇宙中,用rtypeclasses而不是对象。为什么可以' Tonad只是一个你拯救的课程?

Class Functor(f(_),a)延伸到f(a){map(b)(fn:(a){b}):f(b)} class monad(f(_),a)扩展算子(f,a)延伸f(a){静态(f,a)单元(值:a):f(a)flatmap(b)(fn:(a){f(b)}):f( b)地图(b)(fn:(a){b}):f(b)= flatmap((它){单位(fn.call(it))})}

静态成员可以是抽象的,可以被覆盖。您可以在类型参数上调用staticMethod。

这里的真实诀窍在于这延伸了f(a)。 Where子句是借来的,从Ceylon' s给定的子句借来,并定义了Typeparameters上的约束。这是一种始终指的魔术类型,即偶数继承。如果类T继承Monad,则这将延伸F(a)的约束将成为t延伸f(a)的位置。

因此,要定义列表Monad,您将编写类列表(a)扩展Monad(列表,a)。一个Monad看起来像(a,b)延伸monad((_,b),a)-note那个Monad的第一个参数是缺点的,不仅仅是水板。

这是一个真正的monad类型。但它也是完全oo的'没有免费的功能,noalgebraic数据类型,没有键盘。

错误处理的替代方法是现代语言的常见方法。我认为新的OO语言仍应键入,分层组织的ErrorObjects。但不需要异常投掷和堆叠展开。

Go和Rust提供两个替代方法来处理。这两个过程都是值,但去使用多个返回值来返回错误状态,而RURT使用结果Monad。自从我们已经确定,这位规模可以轻松地将Monad定义为班级,错误Monad似乎是理想的,可能有语法支持,如Rust' s try!

类和类型是非常相似的。大多数语言都有一个或另一个,但不是两者。 Scala都有两者,但它的类型是klduds,Andey'从普通类和接口中完全分开的东西。

Monad示例显示,通过一些额外的功能,类可以通过功能语言进行最多的类型。

但我们还可以添加扩展方法和类型的独立实例,它创建类似于生锈的代数和#39; s或haskell' s。

//将SUM方法添加到intsezense列表中列表(int){sum():number = refile((a,b){a + b},0)} //将可比实例添加到ComparableSextension比较列表中(a将列表(a)的比较(a)扩展为可比(列表(a)){比较(即:列表(a)):comparison = // ...实现省略}

扩展将新方法添加到现有型号中,并可能是新的超类。扩展名必须具有名称(由PureScript启发的限制),并且该名称可以用若干合格的方法和字段名称,或者作为演员使用。该名称可确保始终可能的ambiguation。

Class monoid(a)延伸{静态(a)空:组合(x:a):a}扩展int作为monoid(int){静态空= 0组合(x:int):int = this + x} int的扩展名为monoid(int){静态空= 1组合(x:int):int = this * x}列表(a)的扩展(a)作为monoid(列表(a)){静态空= list.nil组合(后缀:list(a))= foldright(list \ cons,suffix)//是的,我知道,我没有定义列表\ foldright}

如果要将INT传递到占用MOOL的函数,则会将其指定其MOOIOD实例(1为ADD,1)。 MoreCommon使用案例将是monoids列表中的折叠方法:listofints.list(添加)\ fold()或listofints.list(乘以)\ fold()。

基于内部类的总和类型几乎工作,但是在那里' s仍然是代数数据类型拼图的一个缺失:模式匹配怎么样?套管徽标定义了一种模式匹配的破坏性形状,但正常的构造乐队' t。

模式匹配不会在纯OO中工作。您可以使用继承创建和类型,并且只有亚型本身可以区分它们的类型;如果您需要在SUM类型上匹配的Anexternal函数,则使用Visitor模式,使用Instanceof。这是笨重的,所以scala而不是提供匹配的andcase类,并允许您完成功能的方式。

//访问者模式(awkward)类protevisitor扩展optionvisitor(String){disitsome(value:string){print("有一些$ {value}")}访问没有(){print("什么都没有")}}一些。新闻(" foo")。访问(printvistor.new())//匹配(简单,但不是oo)的一些.new(" foo&# 34;)匹配{案例一些(值)=>打印("有一些$ {value}")案例none =>打印("没有什么")}

从理论上讲,您可以使用扩展方法在现有的和类型上的VisitorPattern等内容创建内容,这些总和类型' t支持它。

私人课程访客{访问()}私人扩展访问选项作为访问者{vight(){}}私有扩展访问某些(字符串){verse(){//注意我们'重新在A`范围内一些(串)`,//所以`value`指的是“一些”和“公共安”的“价值”字段。打印("得到了一些$ {value}")}}私有扩展访问None {setave(){print("没有")}}一些.new(&#34 ; foo")。访问()

但这仍然是很多样板。让' s创建一个新的匹配语法在引擎盖下,同时剩下简单,如scala' s matchExpression:

每个作为子句匹配类型,然后调用其正文在值的范围内。注意这里的魔力:值为身体的范围,它是指某些\值。这......可能太令人困惑了。但它'显示内部课程已经在Java中工作(描绘了外部类别的内部类'在外层' s的范围内,它给我们一个匹配声明,而无需致命的破坏性语法。

我们还可以添加警卫(可能在哪里或if)来使这些匹配级别更强大,越来越靠近全功能的ML类似匹配。

你可能已经注意到了一些东西" off"关于我使用了最后一节的扩展方法的方式。使用它们是很高兴这样的,它与关于继承和多态的Oointituity同步。但是,如果扩展方法像TypeClasses一样播出,则它们aren' t虚拟。扩展实例基于对象' s编译时类型,而不是其运行时类型,因此匹配声明将始终调用Windows选项上的访问访问权限,并且它不会做任何事情。

我注意到我写了这个虫子的这个错误,所以我可以在这里锻炼。

从技术上讲,我们不需要虚拟扩展方法。匹配和扩展方法之间的等价性很好,但主要是无关紧要的。匹配可以用uck umbuseof匹配在引擎盖下面,并完成工作。

但非虚拟扩展方法似乎似乎是一个脚步。如果你'重新想法oo,你希望每种方法都是虚拟的。如果在车辆上定义了一种方法,请在汽车上覆盖它,然后调用恰好是汽车的车辆参数的方法,' D期望获得覆盖方法,但你赢了' t。

和虚拟扩展方法几乎是不可能的。与钻石问题不同,重叠覆盖可以'易于检测;他们可以来自任何地方。扩展方法依赖于进口范围,但是这适用于Aren' t的ToSubtypes即使在范围内?

实际解决方案可能是禁止从超额输入方法禁止的扩展方法。这使得它们不虚拟定义,但removesthe footgun。它使访问示例上面无效,但......

除了那么简短的绕道进入虚拟延伸方法疯狂,我真的很喜欢这种语言变得越来越多。它很像Scala,但概念上的IT'只有一小部分必要的功能。这使它类似于kotlin,但没有JVM兼容性的行李。

这种语言添加的新功能,超出了scala和kotlin已有产品,是oo兼容的更高含义类型,类似于错误处理的替代方法。

我意识到那里的语言没有太多的东西 - 这个空间是众所周心的东西 - 但它的梦想&#39 我的这种语言的暂定名称是"升降机" 因为Scala意味着梯子,电梯是一个更好的阶梯; 还因为"举起" 是Monadic功能规划的常见操作。 我打开Tobetter建议。