简体   繁体   English

Java中的抽象?

[英]Abstraction in Java?

Today i heard from my friend, that encapsulation is not only achieving information hiding but also abstraction.今天听朋友说,封装不仅是实现信息隐藏,还实现了抽象。 How does it achieve?它是如何实现的?

public class employee {

     private String name;
     private int id;

     public void setName(String name){
         this.name = name;
     }

     public String getName(){
         return name;
     }
}

The above example achieves encapsulation where i am allowing the class to access my public method rather than private members, but where does the abstraction come into picture here?上面的例子实现了封装,我允许类访问我的公共方法而不是私有成员,但是抽象在这里出现在哪里? Can anyone explain me on abstraction in a bit clear manner.任何人都可以以一种清晰的方式解释我的抽象。

There's two different things, information hiding and abstraction.有两种不同的东西,信息隐藏和抽象。

Information hiding makes abstraction possible, but it is something different.信息隐藏使抽象成为可能,但它是不同的东西。 For example, using your code例如,使用您的代码

public class employee {

     private String name;
     private int id;

     public void setName(String name) {
         this.name = name;
     }

     public String getName(){
         return name;
     }
}

The id field is actually hidden. id字段实际上是隐藏的。 This allows one to handle ids in a manner that is decoupled from the rest of the program.这允许以一种与程序其余部分分离的方式处理 id。 Your name field is actually hidden too, as you don't access the name field directly, but the code in getName and setName does.您的 name 字段实际上也是隐藏的,因为您不直接访问 name 字段,但是getNamesetName中的代码可以。

Once you hide the structure of the data from the rest of the code, forcing access through methods, it is possible to create a number of replaceable implementations of an item.一旦您对代码的其余部分隐藏了数据的结构,强制通过方法访问,就可以创建一个项目的许多可替换实现。 For example, an employee is a conceptual kind of person , so you could rewrite the above like so:例如, employee是一种概念上的person ,因此您可以像这样重写上面的内容:

public interface Person {
     public abstract String getName();
}

public class Employee implements Person {

     private String name;
     private int id;

     public void setName(String name){
         this.name = name;
     }

     public String getName(){
         return name;
     }
}

Now your code can deal with the Employee as a Person .现在您的代码可以将Employee作为Person After rewriting the rest of the code that doesn't explicitly deal with Employee s to deal with Person s, you could implement other kinds of Person s and leverage the non-Employee specific tasks that are now Person tasks.在重写未显式处理Employee的其余代码以处理Person ,您可以实现其他类型的Person并利用现在是Person任务的非 Employee 特定任务。

public Customer implements Person {
     private String name;
     private integer moneySpent;

     public String getName() {
          return name;
     }
}

So a person searching routine, as long as it only indexes Person objects can now include searches of both Employee s and Customer s.因此,一个人员搜索例程,只要它只索引Person对象,现在就可以包括对EmployeeCustomer的搜索。 This is because the code dealing with Person objects is actually dealing with a higher level abstraction that both Employee and Customer objects share.这是因为处理Person对象的代码实际上是在处理EmployeeCustomer对象共享的更高级别的抽象。

When dealing with Objects on an abstract level, the names of the methods are shared across the abstraction;在抽象级别处理对象时,方法的名称在抽象之间共享; but, the actual code executed depends on the unmentioned underlying type of the object.但是,实际执行的代码取决于对象的未提及的底层类型。 In other words, if you ask a Person (who happens to be an employee) getName() then it will respond with the Employee.getName() function, while a Customer will respond with a Customer.getName() function.换句话说,如果您询问 Person(恰好是员工) getName()那么它将使用Employee.getName()函数进行响应,而Customer将使用Customer.getName()函数进行响应。 Since the code calling getName() is operating on Person s it has no idea which type of person it will be handling, but the apparent change in behavior (the selection of the right block of code on a per-object basis) still happens.由于调用getName()的代码在Person上运行,它不知道它将处理哪种类型的人,但行为的明显变化(基于每个对象选择正确的代码块)仍然发生。 This phenomena is known as Polymorphisim, and if you are first hitting these concepts, you'll hear Polymorphisim as a word used a lot.这种现象被称为多态,如果您第一次接触这些概念,您会听到多态是一个经常使用的词。

An example of polymorpic behavior:多态行为的一个例子:

 public interface Animal {
     public abstract String makeSound();
 }

 public class Cow implements Animal {
     public String makeSound() {
         return "Moo Moo!";
     }
 }

 public class Dog implements Animal {
     public String makeSound() {
         return "Ruff Ruff!";
     }
 }

 public class Sheep implements Animal {
    public String makeSound() {
         return "Baa Baa!";
    }
 }

 // this class demonstrates the polymorphic behavior

 public class Farm {
    public static void main(String[] args) {
       ArrayList<Animal> animals = new ArrayList<Animal>();
       animals.add(new Cow());
       animals.add(new Sheep());
       animals.add(new Dog());

       for (Animal animal : animals) {
          // this is where the polymorphisim occurs
          // each animal will make a different sound
          // because the makeSound method is getting
          // bound to different blocks of code based
          // on the exact type of animal class hiding
          // under the Animal abstraction.
          System.out.println(animal.makeSound());
       }
    }
 }

expected output:预期输出:

 Moo Moo!
 Baa Baa!
 Ruff Ruff!

even though we never explicitly changed classes, and we never explicitly changed methods.即使我们从未显式更改类,也从未显式更改方法。 It was the binding of the abstract method to the explicit subclass that was changing, which is something that only happens in systems that support polymorphisim.正是抽象方法与显式子类的绑定发生了变化,这种情况只发生在支持多态的系统中。

@ John your friend is right by implementing the encapsulation you also achieve abstraction. @John 你的朋友是对的,通过实现封装你也实现了抽象。

public class employee {
       private String name;
       private int id;   
       public void setName(String name){ 
         name= name+"something that you want to edit";
         this.name = name;      }   
       public String getName(){  
        return name;      }
   } 

in this way you have edited ur set method and hided the details from the user which is nothing but abstraction... thus by writting getters and setters you hide user to do the unneccessary task...通过这种方式,您编辑了您的 set 方法并向用户隐藏了细节,这只是抽象……因此,通过编写 getter 和 setter,您可以隐藏用户以执行不必要的任务……

public void setName(String name){ 
         /*some internal logic suppose in database you want name 
         *should be added with its id but what user to do with it.*/
         this.name = name;      }   
       public String getName(){  
        /* now suppose you have recieved the name from
        *data base it has id but you want user to know only 
        name then you will write the logic here to show the name.*/
        return name;      }

I know adding id to name is a stupid example but thats what i can think of right now... but consider for a very big project you many times write code in set(or call other method which modifies the parameters of it) then what... suppose you get the name but you want to save it in a encrypted form in db, then what.我知道将 id 添加到 name 是一个愚蠢的例子,但这就是我现在能想到的...... ...假设您获得了名称,但您想将其以加密形式保存在 db 中,然后呢。 User dont care about the encryption but yes you have to... because its uneccesary to the user but important to you.用户不关心加密,但是是的,您必须……因为它对用户来说不重要,但对您很重要。 So that should be in the code of yours but hidden from the user and thats what is all about abstraction*("HIDING THE UNNECCESARY DETAILS FROM USER")*所以这应该在你的代码中,但对用户隐藏,这就是抽象的全部内容*("HIDING THE UNNECCESARY DETAILS FROM USER")*

EDITED:-Go to the source!编辑:-转到源头! Grady Booch says (in Object Oriented Analysis and Design, page 49, second edition): Grady Booch 说(在面向对象的分析和设计,第 49 页,第二版):

"Abstraction and encapsulation are complementary concepts: abstraction focuses on the observable behavior of an object... encapsulation focuses upon the implementation that gives rise to this behavior... encapsulation is most often achieved through information hiding, which is the process of hiding all of the secrets of object that do not contribute to its essential characteristics." “抽象和封装是互补的概念:抽象侧重于对象的可观察行为……封装侧重于产生这种行为的实现……封装最常通过信息隐藏来实现,这是隐藏所有的过程对对象的基本特征没有贡献的秘密。”

from above you can conclude the same从上面你可以得出相同的结论

java official documentation for you to understand when to use interface or abstraction. java官方文档让你了解什么时候使用接口或者抽象。

Also, I couldn't help notice that you were confused between encapsulation and abstraction so here is a simple difference between them for geekforgeeks website另外,我不禁注意到您在封装和抽象之间感到困惑,因此这是 geekforgeeks 网站上它们之间的简单区别

Encapsulation is data hiding (information hiding) while,封装是数据隐藏(信息隐藏)而,

Abstraction is detailed hiding抽象是详细的隐藏

(implementation hiding). (实现隐藏)。

Encapsulation groups together data and methods that act upon the data, data abstraction deal with exposing the interface to the user and hiding the details of implementation.封装将数据和作用于数据的方法组合在一起,数据抽象处理将接口暴露给用户并隐藏实现细节。

I think he's confusing polymorphism with encapsulation.我认为他将多态性与封装混淆了。 Polymorphism can help you achieve abstration.多态可以帮助你实现抽象。

Personally I wouldn't say encapsulation is really about abstraction (though I see how it could be taken that way), it's about only permitting a user to see or do what's necessary - they only see an interface to the class, not its inner workings.就我个人而言,我不会说封装实际上是关于抽象(尽管我知道它是如何被采用的),它只是允许用户查看或做必要的事情——他们只看到类的接口,而不是它的内部工作. In your case it's achieved because you're only ever setting or getting the name of the particular class, you never access the name variable directly and never see how it's stored.在您的情况下,这是因为您只设置或获取特定类的名称,您永远不会直接访问 name 变量,也永远不会看到它是如何存储的。 So you could change the name or type of the name variable to something completely different and the interface to your class would still work and look the same.因此,您可以将 name 变量的名称或类型更改为完全不同的内容,并且您的类的接口仍然可以工作并且看起来相同。 I guess that could be taken in a sense as an abstraction.我想这在某种意义上可以被视为一种抽象。

The definitions are loose, but I'd consider polymorphism to fall more into the realms of abstraction, where you decouple the implementation (say, ArrayList ) from the interface it inherits (say, List .) That way you just deal with the list interface, and the underlying list could be anything, but that's an implementation detail and because you're an abstract level "above" it, you don't need to worry about it.定义是松散的,但我认为多态更多地属于抽象领域,在那里你将实现(比如ArrayList )与它继承的接口(比如List )分离。这样你就可以处理列表接口,底层列表可以是任何东西,但这是一个实现细节,因为你是一个“高于”它的抽象级别,你不需要担心它。 Of course this is a simplification, sometimes you need to know implementation details for performance reasons or if some operations may not be implemented or allowed on your specific implementation.当然,这是一种简化,有时您出于性能原因需要了解实现细节,或者某些操作可能不会在您的特定实现中实现或允许。 But from a loose viewpoint (and a pure OO viewpoint) it holds.但是从松散的观点(和纯粹的面向对象的观点)来看,它是成立的。

Whatever you understand it to be, the most important thing is you understand the logic behind it, why it's a good idea and why it's always better to do things that way (in this case, have fields as private and use getters / setters to access them.)无论你理解它是什么,最重要的是你理解它背后的逻辑,为什么它是一个好主意以及为什么这样做总是更好(在这种情况下,将字段设为私有并使用 getter/setter 访问他们。)

It's mostly encapsulation here, but there is some abstraction as well.这里主要是封装,但也有一些抽象。 By using a method called setName() , code that consumes your class doesn't need to know how you're implementing the operation of "setting a name".通过使用名为setName()的方法,使用您的类的代码不需要知道您是如何实现“设置名称”操作的。 For all they know, you're calling out to a webservice and setting it in a database somewhere.据他们所知,您正在调用 Web 服务并将其设置在某个数据库中。 Or maybe you're ignoring the parameter entirely and setting the name to "Steven" every time.或者,您可能完全忽略了该参数,并且每次都将名称设置为“Steven”。 Those facts are abstracted away from the caller.这些事实是从调用者那里抽象出来的。

I don't think you can prove encapsulation with that particular example.我不认为你可以用那个特定的例子来证明封装。 It's more like this:更像是这样:

interface NameService {
    String getName();
}

Now, tell me: does a class implementing this interface get the name from a flat file, a database, a nosql store, or someplace else?现在,告诉我:实现这个接口的类是否从平面文件、数据库、nosql 存储或其他地方获取名称?

Abstraction is all about a concept/model which cannot be realized / instantiated as such.抽象是关于一个无法实现/实例化的概念/模型。 Abstraction is all about restriction on an object's method/members behaviour to other classes.抽象就是将对象的方法/成员行为限制为其他类。

but where does the abstraction come into picture here?但是抽象是从哪里开始的呢?

you've said it yourself: "allowing the class to access my public method rather than private members" or in other words: allowing other classes to access what they may access, and protecting what they may not.你自己说过:“允许类访问我的公共方法而不是私有成员”,或者换句话说:允许其他类访问他们可能访问的内容,并保护他们可能访问的内容。

the abstraction here comes from the public methods, for instance in getName() you don't need to always give the private member value, it could be appended with other value or even it could give totally different thing.这里的抽象来自公共方法,例如在getName()您不需要总是提供私有成员值,它可以附加其他值,甚至可以提供完全不同的东西。 it's like saying: "tell me your name, regardless how you'd give it to me".这就像说:“告诉我你的名字,不管你怎么给我”。 maybe a better example would be a method named getYourWorkDone() .也许一个更好的例子是名为getYourWorkDone()的方法。 the principle remains the same: "get your work done! how? I don't care how!"原则保持不变:“完成你的工作!怎么做?我不在乎怎么做!”

the encapsulation part is from the private members.封装部分来自私有成员。 this class encapsulates those private members so they are grouped to form the class' state.这个类封装了这些私有成员,因此它们被分组以形成类的状态。

It seems encapsulation and abstraction has got everyone confused.似乎封装和抽象让每个人都感到困惑。 If you ask me, those are poles-apart topics and there is absolutely no scope of confusion in this.如果你问我,这些是截然不同的话题,绝对没有混淆的范围。

abstraction happens when you use "abstract" keyword, and encapsulation happens when you create a class.使用“abstract”关键字时会发生抽象,创建类时会发生封装。 a good implementation of encapsulation involves making all your data members private.封装的良好实现涉及将所有数据成员设为私有。

I wrote a few blog posts that might help you:我写了几篇博文可能对你有帮助:

Learn how to use an Abstract Class in Object Oriented Design 了解如何在面向对象设计中使用抽象类

The Theory of Abstraction抽象理论

Abstraction is done when you want to hide the data.Whereas encapsulation is done when you want to hide both data and code.That is wrapping both data and code which you implement.当您想要隐藏数据时进行抽象。而当您想要隐藏数据和代码时完成封装。即包装您实现的数据和代码。

You can implement abstraction by using abstract class or interface.您可以使用抽象类或接口来实现抽象。 In abstract class we can either write concrete methods or abstract methods but in interface we can only use abstract methods.在抽象类中,我们可以编写具体方法或抽象方法,但在接口中我们只能使用抽象方法。

You can implement encapsulation by using access modifiers like public, protected, private.您可以使用访问修饰符(如 public、protected、private)来实现封装。 These access modifiers control the access of your data ie whether it should be public(can be seen by anyone) or protected(can be accessed only by extended classes) or private(hiding it from everyone).这些访问修饰符控制您的数据的访问,即它是否应该是公开的(任何人都可以看到)或受保护的(只能由扩展类访问)或私有的(对所有人隐藏)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM