目录
引言
Java是一种广泛使用的编程语言,其核心思想是面向对象编程(OOP)。面向对象编程是一种将现实世界中的事物抽象成对象,并通过对象之间的交互来实现程序功能的编程范式。本文将通过通俗易懂的语言,结合本人对老师上课时的示例代码的一些修改与一些想法,以宠物商店这样一个示例阐述我对Java面向对象编程的具体理解。
一、何为面向对象?
1.1基本概念
面向对象编程是一种编程范式,它将现实世界中的事物抽象为对象,通过对象之间的交互来解决问题。在面向对象编程中,程序被看作是一系列对象的集合,这些对象通过相互发送消息来共同完成特定的任务。
1.2与面向过程的对比
要理解面向对象,一般来说都先和面向过程进行对比。为了简化,本文就针对宠物猫和狗,从对宠物的命名,和猫和狗对自己的介绍,猫狗的进食,以及对于狗独特的舔狗这一性质进行介绍。
面向过程编程
面向过程编程将问题分解为一系列步骤,并按照顺序编写函数。例如,定义宠物的数据结构,然后定义函数如setName、setWeight、intro、speak等。
缺点:代码重复、维护困难、扩展性差。例如,如果宠物店有多只宠物,需要记录宠物的姓名等属性,定义函数时参数会更多,更加复杂。
面向对象编程
面向对象编程关注对象本身,考虑各个对象有什么性质(属性),各个对象能做什么(方法)。例如,定义一个Pet类,考虑各个对象的属性和方法,通过对象调用方法来完成任务。下文将结合面向对象的三大主要性质,
二、封装(Encapsulation)
封装是面向对象编程的一个重要特性,它指的是将类的实现细节隐藏起来,只暴露必要的接口给外部使用。它指的是将对象的属性和方法封装在一起,并通过访问控制符(如private、protected、public)来控制对这些属性和方法的访问。
示例代码:
//定义一个 Pet 类
public class Pet {
public String name;
private int age;
protected float weight;
private String color;
// 构造方法
public Pet(String name, int age) {
this(name, age, "Unknown", 0.0f);
}
//重载
public Pet(String name, int age, String color, float weight) {
this.name = name;
this.age = age;
this.color = color;
this.weight = weight;
}
// 设置名字
public void setName(String name) {
if (name.contains("zhangsan")) {
System.out.println("no human being name!");
} else {
this.name = name;
}
}
public String eat(String food) {
return "good";
}
// 获取名字
public String getName() {
return this.name;
}
// 获取年龄
public int getAge() {
return age;
}
// 设置年龄
public void setAge(int age) {
this.age = age;
}
// 获取体重
public float getWeight() {
return weight;
}
// 设置体重
public void setWeight(float weight) {
this.weight = weight;
}
// 获取颜色
public String getColor() {
return color;
}
// 设置颜色
public void setColor(String color) {
this.color = color;
}
// 自我介绍
public void intro() {
System.out.println("I am " + this.getName() +
", I am " + this.getAge() +
", my color is " + this.getColor() +
", my weight is " + this.getWeight());
}
}
在这个例子中,Pet类的age、weight和color属性被声明为private或protected,外部无法直接访问,为了允许外部代码访问和修改这些属性,我们提供了公共的getter和setter方法。用getAge()、setAge()、getWeight()、setWeight()、getColor()和setColor()来获取或设置这些属性的值。
例如在主函数中写出如下代码,输出结果如注释显示。
public class Main {
public static void main(String[] args) {
Pet myPet1 = new Pet("Kitty", 2, "White", 4.5f);
Pet myPet2 = new Pet("Tom", 3);
System.out.println(myPet1.name); //输出Kitty
System.out.println(myPet2.name); //输出Tom
System.out.println(myPet1.getAge()); //输出:2
System.out.println(myPet2.getAge()); //输出:3
//System.out.println(myPet1.age); //无法通过编译
//System.out.println(myPet2.age); //无法通过编译
}
}
顺带提一下,本程序还涉及到了对于方法重载这一基本概念的理解:
重载的方法必须具有相同的名字的方法但是重载的方法具有不同的参数列表。参数列表的不同可以体现在参数的数量、类型或顺序上。这使得返回类型可以不同:重载的方法可以有不同的返回类型。这提高了Java中方法的灵活性。
本示例中myPet1.age无法通过编译,但是能通过myPet1.getAge()这一函数对其年龄这一属性进行修改。说明了通过封装,我们可以控制类的成员变量的访问权限,从而提高代码的安全性和可维护性。在本示例中,还通过在setName方法中检查名字是否包含"zhangsan",我们可以防止不合法的名字被设置。这就是封装的作用。
三、继承(Inheritance)
继承是面向对象编程的另一个重要特性,它允许一个类(子类)继承另一个类(父类)的属性和方法。通过继承,子类可以重用父类的代码,并且可以在不修改父类的情况下扩展或修改其行为。继承的好处是代码的重用性和层次结构的清晰性。
示例代码:
Dog类
//继承 Pet 类并实现 Speakable 和 TianGouAble 接口
class Dog extends Pet implements Speakable, TianGouAble {
public Dog(String name, int age, String color, float weight) {
super(name, age, color, weight);
}
// 实现接口方法 speak
@Override
public void speak() {
System.out.println("666!");
}
// 实现接口方法 tianGou
@Override
public void tianGou() {
System.out.println("I love you my host!");
}
public String eat(String food){
return "I am eating " +food;
}
}
Cat类
//继承 Pet 类并实现 Speakable 接口
class Cat extends Pet implements Speakable {
public Cat(String name, int age, String color, float weight) {
super(name, age, color, weight);
}
public Cat(String name, int age) {
// TODO Auto-generated constructor stub
super(name, age);
}
// 实现接口方法
@Override
public void speak() {
System.out.println("miao miao mi mi miao");
}
@Override
public String eat(String food){
System.out.println("miaomiao~~~~~I am eating " +food);
return "I am happy";
}
}
如对于,猫的属性、方法我们依旧要定义name、age、weight和color属性,以及setName、getName、setAge、getAge等方法,如果没有继承这样一种属性呢,动手写一下,会发现这些代码出奇的一致,因为都是宠物店的宠物,他们同样有很多性质(属性),行为(方法)是相同或者类似的,本实例仅仅列出猫狗两种宠物,假如有很多种类型,则会写出非常多冗余的代码,看起来是代码量增加,但是很多都是ctrl c+ctrl v来进行,没有技术含量,只有在描述猫或者狗独特的属性时,才会用到不同的代码,索性,Java的继承特性,直接帮我们复制下来,对于不同的方法,进行方法重写。
继承这一特性中,super关键字变得尤为重要。super
关键字可以帮助我们在子类中调用父类的构造方法、访问父类的属性和方法,从而实现代码的重用和扩展。在这个例子中,Cat
类的构造方法通过super(name, age, color, weight)
调用了父类Pet
的构造方法,从而初始化了父类的属性。super同样可以访问父类的属性和方法,以及在子类中,如果子类的属性或方法与父类的属性或方法同名,我们可以使用super
关键字来区分它们。
综上在代码中,Cat和Dog类都继承了Pet类。这意味着它们自动获得了Pet类的所有属性和方法。例如,Cat和Dog类都继承了name、age、weight和color属性,以及setName、getName、setAge、getAge等方法。在二、封装这一幕,也展示了,getAGE()函数的使用。继承的好处在于提高代码的重用性和层次结构的清晰性,子类可以在不重复代码的前提下扩展功能。
四、多态(Polymorphism)
多态是面向对象编程的第三个重要特性,它允许不同的类以不同的方式实现相同的方法。多态通常通过方法重写和接口实现来实现。
interface Speakable {
void speak();
}
interface TianGouAble {
void tianGou();
}
在三、继承中@Override,注释着方法重写。
在Main函数中
public class Main {
public static void main(String[] args) {
// 多态:使用父类引用指向子类对象
Pet myCat1 = new Cat("Kitty", 2, "White", 4.5f);
Pet myDog = new Dog("Buddy", 3, "Brown", 10.2f);
// 调用 intro 方法
System.out.println(myCat1.eat("fish"));
System.out.println(myDog.eat("Huotuichang"));
myCat1.intro(); // 输出: I am Kitty, I am 2, my color is White, my weight is 4.5
myDog.intro(); // 输出: I am Buddy, I am 3, my color is Brown, my weight is 10.2
// 使用接口引用指向实现类对象
Speakable mySpeakableCat = new Cat("Whiskers", 1, "Black", 3.8f);
Speakable mySpeakableDog = new Dog("Max", 4, "Golden", 15.0f);
mySpeakableCat.speak(); // 输出: miao miao mi mi miao
mySpeakableDog.speak(); // 输出: 666!
// 使用 TianGouAble 接口引用指向实现类对象
TianGouAble myTianGouDog = new Dog("Rex", 5, "Black", 20.0f);
myTianGouDog.tianGou(); // 输出: I love you my host!
}
}
在代码中,Cat和Dog类都重写了Pet类的eat方法,并且都实现了Speakable接口的speak方法。这意味着我们可以使用Pet类型的引用来指向Cat或Dog对象,并调用它们的eat和speak方法。Dog类实现了TianGouAble的tianGou方法。运行结果如注释所示,体现了多态这一特征。多态提高了代码的灵活性和可扩展性,允许通过父类引用调用子类的具体实现。
本例子中同样体现了抽象这一特性抽象类和接口是抽象的体现。抽象类不能被实例化,只能被继承;接口定义了一组方法规范,任何实现该接口的类都必须提供具体实现。在这个例子中,Speakable和TianGouAble是接口,定义了speak()和tianGou()方法,Cat和Dog类实现了这些接口并提供了具体的方法实现。通过接口,我们可以实现多态,即使用接口类型的引用来指向实现该接口的类的对象。
五、小结
Java面向对象编程(OOP)通过封装、继承、多态和抽象等核心概念,显著提升了代码的模块化、可维护性和扩展性。封装通过隐藏实现细节,增强了代码的安全性和维护便利性;继承则促进了代码的重用,并提供了清晰的层次结构;多态性则增加了代码的灵活性和可扩展性。此外,方法重载也进一步提升了代码的灵活性和可读性。OOP的基本理念是将现实世界中的事物抽象为对象,并通过对象之间的交互来实现程序功能。理解和掌握这些核心概念,对于编写高质量的Java代码至关重要。这些特性共同使Java成为一种强大且灵活的编程语言,适用于各种复杂的应用场景。本人因为选修Java课,则相当于学习三个月左右,初识面向对象编程,以上仅仅代表自己的观点,示例代码也大多为老师上课所讲代码进行小部分修改,以及自己的一些理解,还希望有高手进行指点,或者一些学习Java编程的同学们一起交流进步。