为什么隐藏一个类实现? [英] Why hide a class implementation?

查看:60
本文介绍了为什么隐藏一个类实现?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我坚持这个概念。


这是我在一个网站上看到的解释的一部分:


隐藏实现


面向对象设计的主要考虑因素是将变化的事物与保持不变的事物分开。
这对于图书馆尤为重要。该库的用户(客户端程序员)必须能够依靠他们使用的部分,并且知道如果发布新版本的库,他们将不需要重写代码。另一方面,库创建者必须具有进行修改和改进的自由,以确保客户端代码不会受到这些更改的影响。
这可以通过约定来实现。例如,在修改库中的类时,库程序员必须同意不删除现有方法,因为那样会破坏客户端程序员的代码。但是,相反的情况更加棘手。对于字段,库创建者如何知道客户端程序员已经访问了哪些字段?对于仅属于类实现的一部分的方法,也并不适用于客户端程序员直接使用的方法。但是,如果库创建者想要删除旧的实现并放入新的实现,该怎么办?更改任何这些成员可能会破坏客户程序员的代码。因此,库的创建者身穿紧身衣,无法更改任何东西。


但是我无法想象发生这种情况的真实情况。 / p>

有人可以给我看一个现实的例子吗?


我是这样想的:

  public void print(String message)
{
System.out.println(message);
}

如果库客户不知道此实现,会有什么不同?

解决方案

实现并没有真正隐藏。特别是因为您将要使用的大多数库都是开源的。在这种情况下,隐藏是指不属于公共API的任何内容。库的公共API由库公开的公共方法和字段组成。库发布版本后,它应继续在将来的版本上支持公共API。其他任何东西都被认为是隐藏的,该库的用户不能依赖该库的未来版本中存在的隐藏代码。



编辑:


但是,例如,如果客户端未隐藏代码,客户端如何依靠代码呢?


因此,可以说一个库提供了一种类似如下的方法

  public void doSomething(CharSequence X); 

这是未公开的,因为它是公共的。作为该方法的用户,我希望该方法存在于该库的将来版本中。因此,我期望该方法的输入为 CharSequence 。如果该库的作者希望将其更改为 String ,那将是错误的。他们不应将 CharSequence 更改为 String ,因为以前版本的用户期望当库的先前用户升级到新版本时,将CharSequence 并将其切换为 String 可能会产生负面影响。在这种情况下,代码可能无法编译。



因此,基本上,如果它不是隐藏的(又是公共API的一部分),那么作者不应该对它进行任何更改。



这一直在出现,并且有很多解决方法。例如,当 log4j 升级到版本2时,它们的更改非常剧烈,以至于其API必须中断,因此创建了一个名为 log4j 2的全新库。 。因此,它是一个完全不同的库,具有不同的包名称。它不是旧库的新版本,而是名称相似的新库。



与此相反,请看一下Java SE的 HashTable 类。这是旧类,不应再使用。但是Java有一个严格的规则,即新版本中仍必须支持以前版本的旧公共API。因此Java无法完成 log4j 的工作。



另一个例子是Spring。 Spring尝试遵循Java所采用的方法,因为您只需要更新版本,旧代码就可以工作。但是Spring确实不赞成使用其部分公共API。它将删除公共的旧类和方法,但实际上不希望人们再使用。例如,在这种情况下,作为Spring的用户,我可能很难从版本1升级到版本4。主要是因为某些公共API可能已被弃用。



因此,在这里,我给出了三种不同的方法来解决库作者的这种问题。



1)一边执行旧版本,然后创建一个全新的库。例如。 Log4j。
2)严格要求,并始终支持旧的公共AIP。例如。 Java。

3)慢慢弃用旧的公共API方法或类。例如。春天。



作为这些库的用户,我希望支持旧的公共API。我用了所有这三个例子。我不得不在要升级到Java 8的旧代码上使用旧的 HashTable 类,并且很高兴它仍然受支持。我感到从 log4j 1升级到 log4j 2 的痛苦。我还对一个复杂的项目升级了Spring,并产生了需要解决的不利影响。我可以告诉您,对上述库的用户来说,严格遵守旧的公共API最容易。


I'm stuck on this concept.

This is part of an explanation I saw on a site:

Hiding the Implementation

A primary consideration in object-oriented design is separating the things that change from the things that stay the same. This is particularly important for libraries. Users (client programmers) of that library must be able to rely on the part they use, and know that they won't need to rewrite code if a new version of the library comes out. On the flip side, the library creator must have the freedom to make modifications and improvements with the certainty that the client code won't be affected by those changes. This can be achieved through convention. For example, the library programmer must agree to not remove existing methods when modifying a class in the library, since that would break the client programmer's code. The reverse situation is thornier, however. In the case of a field, how can the library creator know which fields have been accessed by client programmers? This is also true with methods that are only part of the implementation of a class, and not meant to be used directly by the client programmer. But what if the library creator wants to rip out an old implementation and put in a new one? Changing any of those members might break a client programmer's code. Thus the library creator is in a strait jacket and can't change anything.

But I can't imagine a real situation where this can happen.

Can someone show me a practical example of this in real life?

This is how I imagine this:

public void print(String message)
{
     System.out.println(message);
}

What difference does it make if a library client knows this implementation or not?

解决方案

The implementation is not really hidden from view. Especially since most libraries out there that you will use are open source. "Hidden", in this case, refers to anything that is not part of the public API. The public API of a library consists of the public methods and fields that a library exposes. Once a library releases a version, it should continue to support the public API on future versions. Anything else is considered hidden and users of that library cannot rely on that "hidden code" being there in future version of that library.

EDIT:

But how could the client rely on code if it was not hidden, for example?

So lets say that a library comes out with a method that looks like this

public void doSomething(CharSequence x);

This is considered not hidden because it is public. Me as a user of that method is expecting it to exist in future versions of that library. So I am expecting that the input to that method is a CharSequence. If the author of that library wants to change that to String then that would be wrong. They should not change that CharSequence to a String because the users of the previous version are expecting CharSequence and switching it to a String might have negative consequences when the previous users of the library upgrade to the new version. In this case, the code might not compile.

So basically, if it is not hidden (aka part of the public API) then the author should not make any changes to the public API that would make previous versions of the library to not work.

This comes up all the time and there are ways around it. For example, when log4j upgraded to version 2, their changes were so dramatic that their API had to break and hence created a whole new library called log4j 2. So its a completely different library with different package names. It is not a new version of the old library, its a new library with similar name.

As a contrast to that, take a look at the Java SE's HashTable class. This is old class that should not be used anymore. But Java has a strict rule that the old public API of previous versions must still be supported in new versions. So Java cannot do what log4j did.

Another example is Spring. Spring tries to follow the approach that Java did, in that you only need to update the version and your old code should work. But Spring does deprecate parts of its public API. It will remove old classes and methods that are public but that it really does not want people to use anymore. In this case, me as a user of Spring might find it hard to upgrade from version 1 to version 4, for example. Mainly because some of the public API might have been deprecated.

So here I have given three different ways library writers have tackled this situation.

1) Side steps the old version and create a whole new library. E.g. Log4j. 2) Be strict and always support old public AIP's. E.g. Java.
3) Slowly deprecate old public API methods or classes. E.g. Spring.

Me as a user of these libraries would prefer that old public API be supported. I have used all three of those examples. I have had to work with old HashTable classes on legacy code I was upgrading to Java 8 and was happy that it was still supported. I have felt the pain of upgrading from log4j 1 to log4j 2. I have also upgraded Spring on a complicated project and have had adverse affects that needed to be troubleshooted. I can tell you that being strict to your old public API's is easiest on the users of said library.

这篇关于为什么隐藏一个类实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆