我是Scala的新手并且听到很多东西都是Scala中的对象。我不知道的是“一切都是对象”的优势是什么?如果一切都不是对象,我不能做的事情是什么?欢迎举例。感谢
答案 0 :(得分:4)
将“所有内容”作为一个对象的优势在于,抽象中断的情况要少得多。
例如,方法不是Java中的对象。所以,如果我有两个字符串,我可以
String s1 = "one";
String s2 = "two";
static String caps(String s) { return s.toUpperCase(); }
caps(s1); // Works
caps(s2); // Also works
因此,我们在制作大写字母的操作中抽象出字符串标识。但是,如果我们想要抽象出操作的身份 - 也就是说,我们将某些东西传递给一个String,它会返回另一个String但我们想要抽象出细节是什么呢?现在我们陷入困境,因为方法不是Java中的对象。
在Scala中,方法可以转换为 functions ,它们是对象。例如:
def stringop(s: String, f: String => String) = if (s.length > 0) f(s) else s
stringop(s1, _.toUpperCase)
stringop(s2, _.toLowerCase)
现在我们已经抽象出了对非空字符串执行字符串转换的想法。
如果这就是我们需要做的事情,我们可以列出操作等等并传递它们。
还有其他不那么重要的情况(对象与类,原始与非对象,值类等),但最重要的是崩溃方法和对象之间的区别,以便传递和抽象功能就像很容易传递和抽象数据。
答案 1 :(得分:3)
优点是您没有在您的语言中遵循不同规则的不同运算符。例如,在Java中执行涉及对象的操作,您使用调用代码的dot name
技术(静态对象仍使用dot name
技术,但有时使用this object
或{{1推断)内置项(不是对象)使用不同的方法,即内置操作符操作。
static object
主要区别在于Number one = Integer.valueOf(1);
Number two = Integer.valueOf(2);
Number three = one.plus(two); // if only such methods existed.
int one = 1;
int two = 2;
int three = one + two;
技术受多态性,运算符重载,方法隐藏以及Java对象可以做的所有好事的影响。 dot name
技术是预定义的,完全不灵活。
Scala基本上将+
运算符作为+
运算符处理,并且定义了这些运算符与对象方法的强一对一映射,从而规避了dot name
方法的不灵活性>。因此,在Scala 中,一切都是对象意味着所有都是一个对象,所以操作
5 + 7
导致创建两个对象(一个5对象和一个7对象),使用参数7调用5对象的plus方法(如果我的scala内存正确地为我服务),并返回一个“12”对象作为5 + 7
操作的值。
这一切都是一个对象在函数式编程环境中有很多好处,例如,代码块现在也是对象,可以传递来回的代码块(没有名称)作为参数,但仍然绑定严格类型检查(代码块只返回Long
或String
或其他任何子类。
当它归结为它时,它使得某些类型的解决方案非常容易实现,并且通常由于不需要处理“移入原语,操纵,移出基元”编组代码来减轻效率低下。 / p>
答案 2 :(得分:3)
我想到的一个特定优势(因为您要求提供示例)是Java中的原始类型(int, boolean ...
),Scala中的对象是您可以通过隐式转换添加功能的对象。例如,如果要向int添加toRoman
方法,可以编写一个隐式类,如:
implicit class RomanInt(i:Int){
def toRoman = //some algorithm to convert i to a Roman representation
}
然后,您可以从任何Int
字面调用此方法,如:
val romanFive = 5.toRoman // V
通过这种方式,您可以“拉皮条”基本类型以使其适应您的需求
答案 3 :(得分:2)
除了他人提出的观点之外,我总是强调Scala中所有值的统一处理部分是一种错觉。在大多数情况下,这是一个非常受欢迎的错觉。 Scala非常聪明地尽可能地使用真正的JVM原语,并且只在必要时执行自动转换(通常称为装箱和拆箱)。
然而,如果自动装箱和拆箱的动态应用模式非常高,则可能存在与之相关的不期望的成本(存储器和CPU)。这可以通过使用 specialization 来部分缓解,当特定类型参数是(程序员指定的)原始类型时,它会创建泛型类的特殊版本。这样可以避免装箱和拆箱,但会以正在运行的应用程序中的.class
个文件为代价。
答案 4 :(得分:0)
并非所有内容都是Scala中的对象,尽管Scala中的对象比Java中的类似物更多。
对象的优势在于它们是状态的包,它们也有一些与它们相关的行为。通过添加多态性,对象可以为您提供更改隐式行为和状态的方法。足够的诗歌,让我们进入一些例子。
if
语句不是scala或java中的对象。如果是,您可以将其子类化,在其位置注入另一个依赖项,并使用它来执行诸如在您的代码使用if
语句时记录到文件的内容。那不是很神奇吗?在某些情况下,它会帮助您调试内容,而在其他情况下,它会让您的头发变得白皙,然后才会发现由于某人覆盖if
行为而导致的错误。
访问一个无对象的,有说服力的世界:对您最喜爱的OOP编程语言进行成像。想想它提供的标准库。那里有很多课程,对吧?他们提供定制方式,对吧?它们采用其他对象的参数,创建其他对象。您可以自定义所有这些。你有多态性。现在想象所有标准库都只是关键字。您将无法自定义,因为您无法覆盖关键字。你会被语言设计者决定实施的任何情况所困扰,而你在那里定制任何东西都会无助。这些语言存在,你很了解它们,它们是类似续集的语言。你几乎不能在那里创建函数,但是为了自定义SELECT
语句的行为,必须出现包含最期望的特征的语言的新版本。这将是一个极端的世界,你只能通过向语言设计师询问新功能(你可能得不到,因为其他更重要的功能需要一些与你想要的功能不兼容的功能)来编程。
总之,并非所有内容都是scala中的对象:类,表达式,关键字和包肯定不是。然而,更多的东西,如功能。 什么是恕我直言,一个很好的经验法则是更多的对象等于更多的灵活性
P.S。例如,在Python中,更多的东西是对象(比如类本身,packages
的类似概念(即python模块和包)。你会看到它是怎样的,黑魔法更容易做,而且带来好的和坏的后果。