欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

面向对象(面向对象真的难吗,你只不过没有理清思路而已)

程序员文章站 2022-03-07 09:10:36
面向对象真的难吗?其实我看不然,只不过我们学习的时候比较杂论,并且也没有真正领悟到他内部的强大。那么开始进入正题,众所周知面向对象三大概念:封装,继承,多态。封装中又可以实现构造方法,方法的重载。继承又体现出方法的重写,从而演变出abstract(抽象类)和interface(接口),而从继承中保留 ......

面向对象真的难吗?其实我看不然,只不过我们学习的时候比较杂论,并且也没有真正领悟到他内部的强大。那么开始进入正题,众所周知面向对象三大概念:封装,继承,多态。封装中又可以实现构造方法,方法的重载。继承又体现出方法的重写,从而演变出abstract(抽象类)和interface(接口),而从继承中保留出来的代码的泄露问题又演变出final和static,最后体现出多态。从这一句话中,我们会发现原来我们学过的面向对象他是一个环环相扣的过程。(小编之前对面向对象也是理解的不是特别的糊涂,自从听了一位北京的大佬讲过之后,发现面向对象其实并没有想象中那么难,希望可以帮助大家)

这是我画的一张面向对象所演变图:

面向对象(面向对象真的难吗,你只不过没有理清思路而已)

由此我们来一步一步的学习面向对象

 

1.封装

      1)   封装其实面向对象中应该是最简单的一部分,get和set方法,但是封装到底是什么呢,讲一个例子,我们都有手机,我们只需要知道他能干吗,能拍照打电话,上网,不需要知道这个手机是哪个厂家生产的,

也不需要手机金属壳是在哪个工厂锻造出来的,这就是封装。

概念: 封装,隐藏对外内容,不许外部直接去操作,必须都在我们控制之下以普通类,把成员变量私有化,改成private要访问这个属性或者设置这个属性怎么办呢?提供gettersetter方法。

 

public class person {
private integer id;
private string name;
private boolean sex;

public integer getid() {
return id;
}

public void setid(integer id) {
id = id;
}

public string getname() {
return name;
}

public void setname(string name) {
name = name;
}

public boolean getsex() {
return sex;
}

public void setsex(boolean sex) {
sex = sex;
}

}

 这个就是一个简单的封装,这些其实大家应该都不陌生。也不算是难点。那我们等一会去调用这个类,现在问题来了,既然这个对象有这些属性,对象是不是也能干一些事情啊,比如说人说sayhello方法,那么我们就在封装下边写一个sayhello方法。

public void sayhello(integer id,string name,boolean sex) {
	this.id=id;
	this.name=name;
	this.sex=sex;
system.out.println("大家好,我叫" + name + "我的编号是" + id); }

  这时候我们就可以做一个测试类去调用他这个类了吧,这时候我们就在新建一个类

public class testperson {
public static void main(string[] args) {
	person person =new person();
	person.sayhello(007, "渣渣辉", true);
}
}

  这里呢输出的时候我们加上性别的属性,在项目开发中,性别属性通常都是用boolean类型去定义,上边的输出我要是加上sex属性,它输出的就是一个boolean类型的值,那么我们完全可以在上边定义一个字符串,在进行if判断把,根据真假值把性别

给字符串,然后在对字符串进行输出就可以吧。

string ssex;
	if(sex){
		ssex="男";
	}else ssex="女";
	

  其实这些都是简单的封装和调用方法,并没有难点,下面我们介绍构造方法

 2)构造方法:什么是类:属性+方法+构造方法 ,利用这个方法来创建对象,如果没有创建java.exe会 进行优化,简单的理解为就是编译器自动给我们这个类增加了一个构造方法。创建类时,会自动调用默认构造方法

                              (所有的类创建必须通过构造方法)那我们就根据上边person类对他写一个构造方法:

public class person {
	private integer id;
	private string name;
	private boolean sex;

	public person() {
		
	}
	
	public integer getid() {
		return id;
	}

  注意:底下的代码我没有加上(节省空间),只需要知道在哪里创建就行(默认的构造方法创建的位置)。

构造方法规定:必须和类名一致

上边的我创建的就是一个默认的无参构造方法,既然有无参的构造方法,那就有有参数的构造方法

 

 

public class person {
    private integer id;
    private string name;
    private boolean sex;

    public person() {
        system.out.println("这里是无参构造");
    }
    
    public person(integer id,string name){
        system.out.println("带参数的构造方法,进行初始化");
        this.id=id;
        this.name=name;
    }

    public integer getid() {
        return id;
    }

    public void setid(integer id) {
        id = id;
    }

    public string getname() {
        return name;
    }

    public void setname(string name) {
        name = name;
    }

    public boolean getsex() {
        return sex;
    }

    public void setsex(boolean sex) {
        sex = sex;
    }

    public void sayhello(integer id, string name, boolean sex) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        system.out.println("大家好,我叫" + name + "我的编号是" + id);
    }

}
public class testperson {
public static void main(string[] args) {
    person person =new person();
    person.sayhello(007, "渣渣辉", true);
    person person1=new person(007,"古天乐");
}
}

 

 

这里是无参构造
大家好,我叫渣渣辉我的编号是7
带参数的构造方法,进行初始化

  

 那上边就是两个构造方法,一个是默认的一个是我们后来自己定义的,在测试类里边我们进行调用可看见person1就是调用的带参数的构造方法,而在上边的带参数的构造方法中我并没有输出出传过去的值。如果想输出值,可以再构造方法里边加上你要输出的

输出语句就可以了。那么我们既然可以定义两个参数的构造方法,那我们可不可以定义一个,或者三个参数的构造方法呢,这个是完全可以的。

    public person() {
        system.out.println("这里是无参构造");
    }
    
    public person(integer id,string name,boolean sex){
        system.out.println("带参数的构造方法,进行初始化");
        this.id=id;
        this.name=name;
    }
    public person(integer id,string name){
        system.out.println("带参数的构造方法,进行初始化");
        this.id=id;
        this.name=name;
    }
    public person(integer id){
        system.out.println("带参数的构造方法,进行初始化");
        this.id=id;
    }

 

 这个就是三个带参数的构造方法和一个不带参数的构造方法,其实到这里你已经把封装中重载已经学完了,当我们定义构造方法时,每一个构造方法的参数个数不一样的时候,我们就成他为重载。

 

重载,方法名称相同,参数个数不同
public person() {}
public person(integer id) {}
public person(integer id, string name) {}

 

 

 2.继承:

              什么是继承呢,我们之前理解的时候都是儿子继承父亲的属性,这个说法其实我感觉不能体现程序,下面我来分享下我对继承的另一种理解,在封装中我们看到了方法的调用就是sayhello方法,那么现实生活中,比如动物,不可能就一个动物会叫,会吃,但是会有一些属性不同,

例如老虎和老鹰,他们两个都可以叫,都吃肉类,但是他们的行走的方式不同,一个是奔跑,一个是飞。那他们两个是不是有共同的属性啊,吃和叫,如果在我们开发过程中以一百个共同的属性,我们难道就要每个类都写一百个吗,就算每个类写了一百了,后期维护的时候加入要修改,

难道我们还一个一个的修改吗,我们为什么不写一个类定义这些他们共有的方法,让老虎和老鹰两个类去连接他,去他那里拿那些方法呢,这样不就节省了大量的时间和空间吗。那么就演变出来了继承 extends 。

n面我们就来创建老虎和鹰这两个类,和他们共有的吃的一个特性类,和一个测试类。

 

 

 首先是老虎和鹰两个公用类的共有特性

public class animal {
 public void eat() {
   system.out.println("吃");
}
}

 

其次是老虎和鹰的行动方式类:这里我们可以看到在建立tiger类后我们在tiger类后边加上了我们继承关键字extends ,在extends在加上要继承的类,这样我们就能把被继承的类的方法拿过来用了。但是并不在这里体现,要在我们建立测试类

后再测试类里边调用

public class tiger extends animal {
    public void run(){
        system.out.println("跑");
    }
}

 

 

public class eagle extends animal {
public void fly(){
    system.out.println("飞");
}
}

 

 下面就是我们的测试类:这里我们可以看待虽然我们tiger中没有eat这个方法,但是因为我们继承了animal类,animal中的类我们就可以拿来用了,并没有报错,证明这种方法时完全可以行的通的

public class test {
public static void main(string[] args) {
    tiger tiger =new tiger();
    eagle eagle =new eagle();
    tiger.eat();
    tiger.run();
    eagle.eat();
    eagle.fly();
    
}
}

 

 这是我们的运行结果:

吃
跑
吃
飞

补充:在我们面向对象中,如果你调用一个类,对他做tostring操作,默认的是不是打印的地址啊,但是如果我们在声明变量时,在source上选择添加一个tostring,我们在去执行tostring是不是打印的就不是地址了,而是你的属性,那么其实这个就是一个重写tostring方法。

 

 

 那在我们实际的项目中经常呢有些系统会二次开发,新增加一些功能或者对之前的某一个功能进行修改,就假如我们上边父类中定义的吃的方法,我现在进行二次开发,我要修改,对吃进行更细化的变更,老鹰吃兔子,

老虎吃肉呢不变,这时候就演变出了我们的重写。其实能重写是非常简单只需要重写父类中的方法,这时候能输出的东西会以子类中的方法进行优先输出。

这时候我们开始对老鹰类进行重写eat方法

public class eagle extends animal {
public void fly(){
    system.out.println("飞");
}
public void eat() {
    system.out.println("我是重写父类的eat()方法,我是老鹰我吃兔子");
}
}

这时候我们测试代码不变在执行测试

吃
跑
我是重写父类的eat()方法,我是老鹰我吃兔子
飞

这个时候我们和上边对比就发现eat在老鹰类中输出的参数就变了。这就是我们重写父类的方法,对父类进行覆盖,下面对继承我们来在练习一个,众所周知java但是单继承机制,子类继承父类之后,那么我们父类可不可以在继承一个类呢,这样就解决了我们

java单继承机制,我用一张图来解释一下

面向对象(面向对象真的难吗,你只不过没有理清思路而已)

儿子继承父亲的,那么父亲继承爷爷的,那么这样我门是不是就可以拿到了爷爷的属性了。那么我们就根据这个来写一个例子。

要求:爷爷:在北京有一套房子,爷爷今年80岁了 

           父亲:有一辆宝马车

            儿子:啥也没有,我只有玩

显然可见,爷爷有两个属性,父亲这里只有一个属性,然后我们儿子继承他们,拿到他们的属性,房子和车子,但是爷爷有一个属性是年龄八十岁了,难道我们那了爷爷的房子,就要变成八十岁吗,显然是不能的,那么就要我们重写爷爷的年龄的方法

public class son extends father {
public void play() {
    system.out.println("我啥都没有,我只会玩");
}

}
public class father extends grandfa {
     public void car() {
         system.out.println("我有一辆宝马车");
     } 

}
public class grandfa {
    public void house() {
        system.out.println("我在北京二环有一套四合院");
    }
    public void age() {
        system.out.println("我今年八十岁了");
    }
}
public class persontest {
    public static void main(string[] args) {
        son son =new son();
        son.play();
        son.car();
        son.house();
        son.age();
    }

}
我啥都没有,我只会玩
我有一辆宝马车
我在北京二环有一套四合院
我今年八十岁了

那么现在我们可以看到儿子拿到了父亲和爷爷的所有的属性,但是又一条是年龄,那岂不是儿子也变成了八十岁,那么解决这个问题有两种方法,第一种,我们重写这个年龄的方法就可以了,第二种,我们直接将他定义成私有的,不让你儿子访问,你调用不了

我年龄的属性是不是就可以了。那么这两种方法我都演示一下:

        a:重写年龄方法:那们我们直接在年龄上重写就可以了,其他的方法是不是不用动啊。

public class son extends father {
    public void play() {
        system.out.println("我啥都没有,我只会玩");
    }

    public void age() {
        system.out.println("我是儿子,但是我今年才二十岁");
    }
}

这时候我们再来执行测试类:

我啥都没有,我只会玩
我有一辆宝马车
我在北京二环有一套四合院
我是儿子,但是我今年才二十岁

唉,年龄是不是就变过来了。这就是我们重写父类的父类的方法,接下来演示第二种

b:将age定义成私有:这时候我们只需要改变父类的age方法就可以了

                  这时候我是不是就像age方法从public公用的改成了私有的private,然后我们在把儿子中年龄方法删除(千万别忘记这一步哦!!!)

public class grandfa {
    public void house() {
        system.out.println("我在北京二环有一套四合院");
    }
    private void age() {
        system.out.println("我今年八十岁了");
    }
}

面向对象(面向对象真的难吗,你只不过没有理清思路而已)

这时候我们清楚的看见当son调用age方法时报错了。这样第二种方法我们就演示完成了。

 那么接下来就出现一个问题,我怎么知道,哪个是父类,哪个是子类呢,即使我子类继承了父类,但是在某一个父类的方法我就是想调用它,我不想要调用子类重写的方法,这个时候怎么办呢,这个java.exe其实早就为我们准备好了,就是下边要说的super关键字。super关键字可能在大家之前学的时候,老师举一些构造的方法来验证他,但是这次,我用一个方法的方式去验证super关键字。请看下边例子。

        定义一个类 ,里边写一个show方法。

public class father {
    public  string show(string name){
        system.out.println("父类"+name);
        return name;
    }

}

再写一个子类去继承父类重写父类的show方法,ex是我写的一个调用的方法。

public class son extends father {
    public string show(string name){
        system.out.println("子类:"+name);
        return name;
    }
public void ex(){
    show("儿子");
    
    
}
public static void main(string[] args) {
    son son =new son();
    son.ex();
}
}

我们来运行程序,这时候系统默认调用的是子类重写父类的show方法。

子类:儿子

现在正式来说明我们的问题,我们不想调用子类的show方法,调用父类的show方法:

public class son extends father {
    public string show(string name){
        system.out.println("子类:"+name);
        return name;
    }
public void ex(){
    show("儿子");
    super.show("父亲");
    
}
public static void main(string[] args) {
    son son =new son();
    son.ex();
}
}

只需要在show方法前边加上我们的关键字super,我们看下程序的运行结果:

子类:儿子
父类:父亲

     继承是非常好的,但是也有不好的地方,破坏父类结构,父类中暴露公用,可以通过子类重写父类方法,恶意代码。

那么现在又出现一个问题:我想规定继承方法必须子类去实现。(

举例:就好比说在我们工作中,我们都会有一个小组长,小组长在收到上边的项目后,安排组员做东西,做一块是不是就是一个方法啊,现在我们的小组长规定是我的组员,你就必须把这个活给我干

了。那么就演变出我们的抽象类抽象类。

首先我们创建抽象类,抽象类的关键字abstract,(抽象类定义:抽象方法必须在抽象类中,抽象类中可以没有抽象方法       学过的人自然就理解,如果没有学过的也不用着急,下边我们会具体的体现)

 

这是我定义的抽象类 在public后边加上abstract,这样我们这个类就是抽象类(或者在创建项目的时候选择创建抽象类) abstract这个关键字放在public前后都是可以的,都不会报错,只不过默认的是放在public后边的

下边的代码我加上之后如果你放到编译器中,在project2哪里就会给你报错,为什么报错呢?我们看一下 :鼠标放上去后提示英文的意思为,将这个peoject2方法加上 abstract,如果我们不加abstract的方法是不是就是普通的方法

加上abstract 就变成了抽象方法了, 

 

public abstract class group {
    public void peoject1(){
        system.out.println("项目一比较重要,我是组长我来干");
    }
    public abstract  void project2(); }

那么到现在我们还不足以验证上边抽象的结论:下面我们讲group方法的修饰词abstract关键字去掉:

 

面向对象(面向对象真的难吗,你只不过没有理清思路而已)

我们看见又报错了,这时候我们的方法中是不是有一个抽象方法啊:project2 ,我们把鼠标放在group上选择第一个系统提示的,整个程序就会恢复正常了

这样就验证我们的抽象类的定义,抽象方法必须定义在抽象类中

面向对象(面向对象真的难吗,你只不过没有理清思路而已)

下面来进行我们的操作,做抽象,所谓抽象只不过是一种定义,他的主要规则是,我在抽象类中定义的抽象方法,子类必须实现,大家呢不要把他想的太过复杂,他其实也是一个父类,只不过加上来规范

下面我们来创建一个类来继承我们得抽象类。

面向对象(面向对象真的难吗,你只不过没有理清思路而已)

现在我们看,我这个组员这个类怎么又报错了呢,鼠标放在红线上选择第一个,哎,系统是不是帮我们创建了一个方法啊。哎这个方法的名字是不是就是和我继承的父类的抽象方法一样啊,这样就体现了我们的抽象类了

定义的抽象方法,子类必须去实现。

面向对象(面向对象真的难吗,你只不过没有理清思路而已)

 

public class crew extends group{

    @override
    public void project2() {
        system.out.println("我是组员,我干简单的活");
        
    }

}

下面是测试类和输出的结果

public class test {
    public static void main(string[] args) {
        crew crew =new crew();
        crew.project2();
    }
}
我是组员,我干简单的活

 

现在问题又来了,抽象类是不是里边有可以自己的方法,就好比我们上边的例子,小组长是不是也有自己的活啊,那么现在我的要求变了,我现在是项目经理,我就啥也不相干,我就管分配任务,哎,我们的接口就这里演变出来了

接口是一种变相的继承,继承定义父类,让子类去继承,接口是我们定义一个接口,让其他的类去接入他。

首先我们创建接口的时候就不是创建类了,在选择创建的时候在与class下边第二个会有一个interface词,我们选择这个创建我们的接口:现在我是项目经理,我定制了一个项目,我让我的组员去做;

public interface manager {
    public void pro1();

    public void pro2();

    public void pro3();
}

 

 下面我们去接入接口:

 定义一个员工类,那么我们接入的时候就用到我们的关键字了implement,我们接入后会发现,哎又报错了,我们说接口是从抽象类演变过来的,是实现我项目经理规定项目,组员去实现项目的过程,

面向对象(面向对象真的难吗,你只不过没有理清思路而已)

我们把鼠标放在红线上选择第一个,这样就不错了,让我的实现类去必须去实现这些方法

public class crew implements manager {

    @override
    public void pro1() {
        system.out.println("做的是项目1");

    }

    @override
    public void pro2() {
        system.out.println("做的是项目2");
    }

    @override
    public void pro3() {
        system.out.println("做的是项目3");
    }

}

 

 

这样之后我们建立测试类:哎,我们发现又报错了,这个时候我们先不看报错信息,我们看你调用的是manager,manager接口他里边只有一些方法,并没有实现这些方法,就是说,项目并不是项目经理做的,而是他的手下做的。

面向对象(面向对象真的难吗,你只不过没有理清思路而已)

那么怎么解决呢:讲我们后边new的后边不去newmanager,我去new真正实现这些项目的类啊:

public class test {
    public static void main(string[] args) {
          manager m =new crew();
    }
}

 

这样之后我是不是就不报错了,然后我们在去调用那些方法:

public class test {
    public static void main(string[] args) {
          manager m =new crew();
          m.pro1();
          m.pro2();
          m.pro3();
    }
}
做的是项目1
做的是项目2
做的是项目3

 

这就是我们的接口实现。

在我们现实中,经常会有一些项目会二次的开发,那么之前呢,美国发生过一个案件,在银行,有一个程序员在给银行的系统做开发之后,做了一些修改,什么修改呢,每个用户存钱之后都会给他这个程序员的账户转账一美分,那我们知道一美分并不多,

但是有无数的人在往银行存钱啊,这样他就获取了当量钱财,那么他在开发的时候,是不是就是重写了系统的加密算法啊,这样子类的方法就覆盖了父类的方法,这样就实现了给他赚钱的目的,那么我们为了防止这种现象的发生,我想定义一个一个类

我让一些方法可以去让子类重写,一些加密的类我不让你去重写,或者整个类我都不让你去继承,这时候就演变出来我们的final关键来,final关键字,不允许去继承和重写。

我现在就把上边继承的案例爷爷,父亲和儿子的案例做了一下修改,我吧grandfa类加上final ,哎我们看父亲的类和儿子的类还有测试类都报错了,一旦定义了是不是就不让他们继承了,那测试调用爷爷的方法是不是也就不成立了,

 

面向对象(面向对象真的难吗,你只不过没有理清思路而已)

 

 

3.多态

       多态是面向对象中最难的一块,为什么难呢,小编之前也是在csdn,博客园上看了众多的案例,是当时的案例理解了,但是我感觉别人问我,多态是什么,我还是回答不上来,为什么会这样,你这个案例你虽然懂了,但是多态的本质你并没有理解,

我们先不看多态,我们先看上边的封装和继承,我们发现最后我们的测试的时候啊,是不是直接调动的方法,而方法里边的东西是不是都写死了,对把,你在现实的开发中你写死的东西有哪些不好,是不是不利于维护啊,这样才演变出来我们的多态,下面我

说一下我对多态的理解,就一句话,

不到最后调用,我永远不知道我要干什么。

这句话现在看的话肯定是看不懂的,具体的我们要在例子中去体现,那么之前我们做某些方法的时候是不是就是传就是参数,固定的参数,固定的方法,固定的去执行这个方法,对不对,那么现在我在传的参数的时候我不传固定值了,我就去传一个能代表的

参数去替代他,到时候我们调用的时候我们再去说我是谁,我要干嘛对不对。就好比我们4s店,众多的车,不同的价格,对不对,你见那个买车的人去直接买固定的车,是不是都是相中那个了,我再去选择去购买那个车。好下面我就以买车为例:

先来分析一下:

                         a:我们是不是得有一个车得类:car(接口和抽象类都可以)小编这里呢我就定义一个接口。

                         b:车的类里边只不过是车的方法,车的价格,但是具体哪个车就得体现来:我们来定义两个类:一个叫宝马(bm)一个叫奔驰(bc)

                         c:现在万事俱备只欠东风了,车,车的品牌价格都有了,我们是不是得有一个人去卖车啊:是不是的又一个sellcar的类去卖车啊

                         d:测试类

好我们按照步骤一步一步的来创建:两个方法一个品牌,一个价格

public interface  car {
    public   string getname();
    public  integer getprice();
}

 

两辆车

public class bm implements car {

    @override
    public string getname() {
        return "宝马";
    }

    @override
    public integer getprice() {
        return 300000;
    }

}

 

 

public class bc implements car {

    @override
    public string getname() {
        return "奔驰";
    }

    @override
    public integer getprice() {
        // todo auto-generated method stub
        return 5000;
    }

}

 

 这样我们的车就搞好了,该卖车了,首先定义他的属性,没有什么可说的。

public class sellcar {
    private integer money=0;
    private integer sum=0;
    public integer getsum() {
        return sum;
    }
    public void setsum(integer sum) {
        this.sum = sum;
    }
    public integer getmoney() {
        return money;
    }
    public void setmoney(integer money) {
        this.money = money;
    }

}

 

 下面的才是重点,我定义一个sellcar方法:但是大家注意我传的参数是什么是不是接口的参数啊,这个才是真正体现面向对象的概念

public void sellcar(car car) {//动态体现   
        system.out.println("型号"+car.getname()+"价格        "+car.getprice());
        money+=car.getprice();
        sum+=1;

    }

 

 测试类:这里是不是到了最后我才说我要买奔驰车,之前是不是不知道,这样就体现了那句话:

不到最后调用,我永远不知道我要干什么。

public class testcar {
    public static void main(string[] args) {
        sellcar sellcar =new sellcar(); 
        car car;//体现多态
         car=new bc();
         sellcar.sellcar(car);
         system.out.println("销售总额为:"+sellcar.getmoney()+"    销售车的数量为"+sellcar.getsum());
         
    }
}

 

运行结果:

型号奔驰价格        5000
销售总额为:5000    销售车的数量为1

 

 其实这只不过是一个简单的例子:因为就一个接口,我们也可以定义两个接口的项目,来一个小动物喂食的例子,那么多态体现的方法有很多很多种,

需求分析:动物:小猫。小猪

                 食物:鱼          米饭

   两个接口就在这里了,是不是就是上边我们的车啊,然后在创建四个类去体现他

下面就是饲养员了,最后是测试类

动物接口类:

public interface animal {
    public string getanimalname();
}

 

动物具体类:

public class cat implements animal{

    @override
    public string getanimalname() {
        return "猫";
    }

}

 

 

public class pig implements animal {

    @override
    public string getanimalname() {
        // todo auto-generated method stub
        return "猪";
    }

}

 

 食物接口类:

public interface food {
       public  string getname();
}

 

食物具体类:

 

public class fish implements food {

    @override
    public string getname() {
        return "鱼";
        
    }

}

 

 

public class rice implements food {

    @override
    public string getname() {
        return "米饭";
    }

}

 

 上边这些都没有什么技术可言,真正体现的还是后边的:这里定义喂食方法,里边的参数是不是活的,不是死的,和上边的卖车一样最后我测试调用的时候,才能或取到参数。

public class feeder {
public void feed(animal animal,food food) {
    system.out.println(animal.getanimalname()+"吃"+food.getname());
}
}

 

 测试类:

public class test {
    public static void main(string[] args) {
        feeder feeder = new feeder();
        animal animal;
        food food;
        animal=new cat();
        food =new fish();
        feeder.feed(animal, food);
        animal=new pig();
        food =new rice();
        feeder.feed(animal, food);
    }

}

 

 

猫吃鱼
猪吃米饭

 

 

整体的到这里就结束来,小编感觉如果能把这些案例理解,就算你不能真正的理解面向对象,是不是对面向对象抽象有了一个系统的概念,感觉他并不是那么抽象,那么难以理解。希望可以帮到大家!!!