什么是面向对象思想?已经学完了java确不知道如何跟别人解释面向对象是什么意思这很常见。让我们一起来回顾下这个奇思妙想~
文章目录
现在越来越多的高级语言流行起来了,如大家耳熟能详的c++,python,java等,这些都是基于面向对象的语言
而最最基础的,学校必学的语言----c语言它是属于面向过程的语言。
好了,现在让我们来讨论下这两类语言的区别
面向过程:
就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
举例来说,大象装进冰箱需要几步?

按照面向过程思想:
第一步:工作人员去打开冰箱门
第二步:把大象塞进冰箱
第三步:工作人员把冰箱门关上
诶,这里我们就看出来了,面向过程就是把一件事按步骤一步一步来实现
用代码表示
public void openDoor(){} //开门
public void putIn(){} //装冰箱
public void closeDoor(){} //关门
依次调用这些方法就完成了
对象,就是对问题中的事物的抽象
面向对象:
就是把现实中的事物都抽象为“对象”。每个对象是唯一的,且都可以拥有它的属性与行为。我们就可以通过调用这些对象的方法、属性去解决问题。
用面向对象思想解决大象装进冰箱
大致的了解到了对象这个概念,可以说是对现实事物的一种抽象映射。

例如在这个事件中:
冰箱作为一个对象;
大象作为一个对象。
冰箱有这些功能:开门、装物体、关门
class fridge{
public void open(大象){} //开门
public void putIn(大象){} //放进冰箱
public void close(大象){} //关门
}
class elephant{
public void eat(){} //吃
}
看出来了什么?每个对象是独立的,有属于它自己的功能,只需要专心实现自己的功能就好。所以在建立对象模型阶段,仅仅关注对象有什么的功能,但不考虑如何实现这些功能。
面向对象的好处,就包括有很好的延展性,比如我给大象赋予了一个吃的功能,它通过调用就可以在冰箱里去吃东西。面向对象就是把现实问题抽象为对象,通过调用每个对象的属性或功能去解决问题。
如果我要修改我的需求,把大象换成兔子,我用面向过程是不是得把每个步骤中的大象改为兔子。而用面向对象解决,我甚至可以重新创一个兔子对象,仅仅在调用的时候选择兔子就行了。
很多人都会创建对象,不就是new嘛,调用对象方法不就是new.方法嘛。结果,有部分人在new类的时候,就下意识的把类当成了对象,那么类到底是不是对象呢?
肯定不是,先给出他们的基本概念
对象
对象是由数据(描述事物的属性)和作用于数据的操作(体现事物的行为)组成的封装体,描述客观事物的一个实体,是构成系统的基本单元。
类
类是对一组有相同数据和相同操作的对象的定义,是对象的模板,其包含的方法和数据描述一组对象的共同行为和属性。类是在对象之上的抽象,对象则是类的具体化,是类的实例。类可有其子类,也可有其他类,形成类层次结构。
1)类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。
2)类是一组具有相同属性和行为的对象的抽象。我们可以将类看做是创建对象蓝图,对象根据这个蓝图去具体实现某个东西。
比如来说,给一张“伞”的蓝图,我们设计出了晴雨伞,剑伞等等,你会发现,这些伞都有相同的行为呀----遮雨。

所以,类的实例化结果就是对象,而对一类对象的抽象就是类,类描述了一组有相同属性和相同方法的对象。
(一)基本概念
封装(encapsulation)即信息隐蔽。它是指在确定系统的某一部分内容时,应考虑到其它部分的信息及联系都在这一部分的内部进行,外部各部分之间的信息联系应尽可能的少。
(二)四种访问控制级别

(三)封装使用
1、把尽可能多的东西藏起来,对外提高简洁的接口
比如有半自动洗衣机和一个全自动洗衣机
半自动洗衣机接口有以下方法
①开机
②关机
③放水
④定时
⑤洗涤
⑥排水
⑦脱水
全自动洗衣机有以下方法
①开机
②关机
③设置洗衣机模式
④开始洗衣服,洗完自动关
对比来看,我们就会发现,自动洗衣机把放水、定时、洗涤、排水、脱水等细节,封装到了③设置洗衣机模式里,这样为使用者提供了更加简单易用的接口,所以自动洗衣机会更加方便。
2、把所有属性藏起来
加入某种属性允许外界访问,那么提供访问该属性的公开方法。假如狗类有一个名字、年龄属性,不允许外界直接访问属性,但允许提供get和set方法来访问
class Dogs{
private String name; //名字
private String age; //年龄
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
那么我们把属性设为private私有,把对外界提供设置属性的方法设置为public。
有些人会问,既然是对外公开的,为什么不直接把name,age属性设置为public呢,反而还要通过方法来设置,会不会多此一举?
不会,有以下四个原因:
(一)符合现实外因通过内因起作用的客观规律
假设原来狗就有一个叫“旺财”的名字,是对象本身原主人取的,调用了setName()方法【内因】。好了,领养狗的主人打算给狗换个名字“大黄”,他是使用者,也是调用setName()方法【外因】。
(二)灵活控制属性的读和修改的访问级别
比如我只能让使用者知道这狗狗的名字,但却不允许修改他。那就吧setName()设为private私有,getName()设为public公有。
(三)防止使用者错误修改属性
直接调用类的属性,万一改错了怎么办。所以我们可以在公有方法setName()里面添加限制条件,防止使用者错误修改属性。例如,狗狗的年龄的范围要在0~20期间。
public void setAge(int age) {
if (age >20 || age < 0){
throw new IllegalArgumentException("口令不合法");
}
else {
this.age = age;
}
}
(四)有助于对象封装实现细节
如果上述判断年龄合法的过程我们不想对使用者公开,就把这个过程用private封装成一个“透明”的方法。这个判断年龄合法的过程对使用者是透明的。
与封装具有相同含义的一个概念就是透明。对象封装实现细节,也就意味着对象的实现细节对使用者是透明的。透明在这里理解为“看不见”
public void setAge(int age) {
isLegal(); //判断是否合法
this.age = age;
}
private void isLegal(){
if (age >20 || age < 0){
throw new IllegalArgumentException("口令不合法");
}
else return;
}
继承:让某个类型的对象获得另一个类型的对象的属性和方法。继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
(一)语法
class A extends B{}
一共继承了哪些东西呢?这要分两种情况
(二)继承父类成员变量/方法
hanqishi继承了父类Dog
class Dog{
public String name="小白";
public void say(){
System.out.println("汪汪汪");
}
}
//哈奇士
class haqishi extends Dog {
public void test(){
System.out.println(name);
say();
}
}
调用haqishi的test()方法,测试如下
小白
汪汪汪
测试结果:子类haqishi继承了父类的成员变量和成员方法
(三)重写父类方法
子类haqishi重写父类Dog的say方法
class Dog{
public String name="小白";
public void say(){
System.out.println("汪汪汪");
}
}
//哈奇士
class haqishi extends Dog {
@Override
public void say() {
//super.say(); 继承父类原有方法
System.out.println("哈哈哈");
}
}
调用子类say方法,测试如下:
哈哈哈
(四)重载父类方法
重载方法必须满足以下条件:
1、方法名相同
2、方法的参数类型、个数、顺序至少有一项不同
3、方法的返回类型可以不同
4、方法的修饰符可以不相同
class Dog{
public String name="小白";
public void say(){
System.out.println("汪汪汪");
}
}
//哈奇士
class haqishi extends Dog {
//重载 改变参数
public void say(String name) {
System.out.println(name+"汪汪汪");
}
//重载 改变参数+返回值
public int say(int age) {
System.out.println("汪汪汪"+age);
return age;
}
}
分别调用
haqishi h = new haqishi();
h.say();
h.say(“哈奇士”);
h.say(6);
结果如下:
汪汪汪
哈奇士汪汪汪
汪汪汪6
多态:对于同一个行为,不同的子类对象具有不同的表现形式。多态存在的3个条件:
1)继承 2)重写 3)父类引用指向子类对象。
public class extend {
public static void main(String[] args) {
Animal a = new Dog();
Animal b = new Cat();
a.say();
b.say();
}
}
abstract class Animal {
abstract void say();
}
//猫
class Cat extends Animal{
public String name="小黑";
public void say(){
System.out.println("喵喵喵");
}
}
//狗
class Dog extends Animal{
public String name="小白";
public void say(){
System.out.println("汪汪汪");
}
}
运行结果
汪汪汪
喵喵喵
理解多态
在这个运行环境中,引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定。Java虚拟机会根据引用变量指向的对象来调用该对象的指定方法,这种运行机制被称为动态绑定
参考文献:《Java面向对象编程(第2版)》- 孙卫琴
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput