类与对象 构造方法 继承 接口详解
什么是类和对象?
我们假设有一个类别叫动物,生活中有很多动物对象,他们都有动物的特性(属性,方法)。
public class Animal{
//属性
private String name;
private int height;
//方法
//定义set方法,初始化属性name
public void setName(String n){
name = n;
}
//定义get方法,得到属性name
public String getName(){
return name;
}
//定义set方法,得到属性height
public void setHeight(int h){
height = h;
}
//定义get方法,得到属性 height
public int getHeight() {
return height;
}
}
什么是父类子类,继承?
动物还可以细分为猴子、大象、狗、猫,这些细分的动物类别也是类,它们共同的都有继承动物(父类)的特性,但同时它们也有自己的特点,那么可以称它们为子类。
public class Daxiang extends Animal{
}
什么是函数的重写
这些动物都有一个会叫的特性,但每个子类,猫啊,狗啊,各自都有不同的叫法,喵喵~或者旺旺!!这就是子类对父类中函数的重写
public class Daxiang extends Animal{
public int getHeight() {
return height + 1;
}
}
什么是函数的构造
每个动物都有共有的属性,比如每个动物都具有的名字,身高,那么我们在创建这个动物的时候,我们就可以通过构造来对属性进行赋值或者进行其他初始化的操作。
public class Animal{
//属性
... 此处省略
//无参构造方法
void Animal(){
name = "未定";
height = 0;
}
//方法
...此处省略
}
什么是无参构造,有参构造?
如果我们没有定义构造函数,那么在创建对象时就会调用默认的无参构造函数,当然我们可以自己定义这个函数方法。
通过创建有参构造函数,我们可以方便的在创建对象操作时通过传递几个参数就进行属性的设置。
当我们自定义有参构造而没定义无参构造时,创建函数对象就必须传递相应的参数。当有参和无参同时出现时,就造成了函数的重载,创建对象时会自动识别传递了哪几个参数来调用相应的构造函数。
public class Animal {
//属性
private String name;
private int height;
//方法
Animal(){
name = "未定";
height = 0;
}
Animal(String n, int h){ //这里使我们的有参构造函数
name = n;
height = h;
}
public void setName(String n){
name = n;
}
public String getName(){
return name;
}
public void setHeight(int h){
height = h;
}
public int getHeight() {
return height;
}
}
什么是向上转型和向下转型?
我们创建一个子类对象,子类对象当然具有父类的特点,但是方法会有重写的情况。当把这个子类对象赋给一个父类对象,系统就会识别是否子类中有方法的重写,如果有,那么这个父类对象调用该方法时就会调用子类中重写的版本。这就是向上转型。
public class Manage {
public static void main(String[] args){
//在主函数中对类对象进行操作
Animal dx = new Daxiang(); //向上类型转换
String dxname = dx.getName();
//输出我们需要的内容
System.out.print(dxname);
}
}
当我们强制父类对象变为子类对象,这个猴子的就又具有了自己独有的方法,而不只是动物的那些特性。这就是向下转型。
Daxiang a = (Daxiang) dx;
什么是接口?
接口像类一样也是一个可以引用的数据类型,接口中定义的变量都必须是静态固定被初始化过得,接口可以实现多继承但是类不可以。当定义了一个类继承了这个接口,这个类中就必须要重写接口中所有的抽象方法。
接口常被应用于给函数传参的时候,事先定义一个接口,在这个接口的规范下来实现需要方法,起到规范输入的作用。
//定义接口
public interface Ac extends EventListener {
public static final int a = 0;
public void actionPerformed(ActionEvent e);
}
//应用接口定义一个要实现的类,接口规范了类的编写
public class ButtonListener implements Ac {
public void actionPerformed(ActionEvent e){
System.out.print("hello");
};
}
//主函数中调用规范后的类对象
ButtonListener listen = new ButtonListener();
button.addActionListener(listen);
类与对象
创建一个类
类本身就是一种自己定义的数据类型
public class Animal{
//属性
private String name;
private int height;
}
第一步:这里我们定义一个Animal类(动物),那么这个动物会有名字、高度,这是我们定义的每个动物都有的属性。
public class Animal{
//属性
private String name;
private int height;
//方法
//定义set方法,初始化属性name
public void setName(String n){
name = n;
}
//定义get方法,得到属性name
public String getName(){
return name;
}
//定义set方法,得到属性height
public void setHeight(int h){
height = h;
}
//定义get方法,得到属性 height
public int getHeight() {
return height;
}
}
第二步:这里就可以定义我们类中方法,我们创建set、get方法来对我们设置的动物属性进行赋值和获取操作
创建一个类对象
public class Manage {
public static void main(String[] args){
//在主函数中对类对象进行操作
//创建一个类对象
Animal dx = new Animal();
//因为这个对象的属性都是私有的,所以需要调用方法进行设定或者获取
dx.setName("大象");
dx.setHeight(20);;
//调用方法获取这个对象的属性
String dxname = dx.getName();
int height = dx.getHeight();
//输出我们需要的内容
System.out.print(dxname + "高" + height +"米");
}
}
运行后得到输出:大象高20米。
这里我们用类这个数据类型创建了一个变量就是类对象。这里要用new在内存中新建出类中的内容。在new的时候我们就调用了函数中默认的无参构造方法进行初始化。
构造方法
无参构造
这里的无参构造方法可以由我们自己进行定义,默认的无参构造方法就会被替代。
public class Animal{
//属性
... 此处省略
//无参构造方法
void Animal(){
name = "未定";
height = 0;
}
//方法
...此处省略
}
这里我们再用new新建一个对象时就可以运行我们自己的无参构造方法啦!
public class Manage {
public static void main(String[] args){
//在主函数中对类对象进行操作
//创建一个类对象
Animal dx = new Animal();
String dxname = dx.getName();
int height = dx.getHeight();
//输出我们需要的内容
System.out.print(dxname + "高" + height +"米");
}
}
输出:未定高0米
重载 + 有参构造
重载就是我们定义了一个与之前定义的函数名字相同的函数,区别在于该函数的参数类型、参数多少、参数顺序总会有不同,如:
public void GG(){ }; public void GG(int a, int b){};
这两个函数可以同时出现在一个类中,当调用这些方法时,可以自动识别传的参数类型、多少、顺序来判断到底是运行哪一个
有参构造就是在无参构造基础上加入了我们自定义的几个需要传入的参数,这样可以方便在创建对象时就进行初始化操作。
无参有参可以同时存在,只需要在新建对象时识别参数就可以判断到底是运行哪一个,这就是重载的威力!
下面让我们看一下这样的代码
public class Animal {
//属性
private String name;
private int height;
//方法
Animal(){
name = "未定";
height = 0;
}
Animal(String n, int h){ //这里使我们的有参构造函数
name = n;
height = h;
}
public void setName(String n){
name = n;
}
public String getName(){
return name;
}
public void setHeight(int h){
height = h;
}
public int getHeight() {
return height;
}
}
public class Manage {
public static void main(String[] args){
//创建一个类对象
Animal dx = new Animal("猴子", 1);//这里进行有参构造
String dxname = dx.getName();
int height = dx.getHeight();
System.out.print(dxname + "高" + height +"米");
}
}
输出为:猴子高1米
继承
继承就是父类的内的属性和方法全部都继承给子类了,语法结构如下所示
public class Daxiang extends Animal{
}
这里的Daxiang
类 就是我们写出的子类,extends
Animal
就可以继承父类Animal中的内容
这里我们重新写一下Animal父类
public class Animal{
private String name;
private int height;
public void setName(String n){
name = n;
}
protected String getName(){
return name;
}
Animal(){
name = "未知";
}
}
由于是继承关系,子类继承了父类的全部内容
因此主函数创建的子类对象调用时就可全部调用这些方法,private需要在方法中进行访问
public static void main(String[] args){
//在主函数中对类对象进行操作
Daxiang dx = new Daxiang(); //注意这里创建的是子类对象
dx.setHeight(20);
dx.setName("小红");
String dxname = dx.getName();
int height = dx.getHeight();
//输出我们需要的内容
System.out.print(dxname + "高" + height +"米");
}
输出为:小红高20米
注意这里创建的是子类对象
向上类型转换
当我们定义一个父类对象,我们new一个子类对象赋给这个父类,这个时候会检测子类中是否有重写父类中的方法,将父类中的对应方法替换为子类中重写的方法,这样不同的子类向上类型转换后调用方法就会有区别。
定义一下子类
public class Daxiang extends Animal {
public String getName(){
return "大象";
}
}
注意:这里重写时 访问修饰符的优先级为 public > protected > private>空。 访问修饰符只可以向上替换,不可以向下替换。
父类还是一样
public class Animal{
private String name;
private int height;
public void setName(String n){
name = n;
}
protected String getName(){
return name;
}
Animal(){
name = "未知";
}
}
主函数
public class Manage {
public static void main(String[] args){
//在主函数中对类对象进行操作
Animal dx = new Daxiang(); //向上类型转换
String dxname = dx.getName();
//输出我们需要的内容
System.out.print(dxname);
}
}
如果是父类中的方法,输出应该为 未知,但这时的输出是 大象,因为上面解释的向上类型转换。
向上类型转换的应用场景就是当你调用一个方法的时候,(函数)方法的参数是一个父类对象,你就可以传一个子类对象,这样,不同的对象就会执行不同的方法。
向下类型转换
就是相当于类型的强转。 (Daxiang) dx
Daxiang a = (Daxiang) dx;
这时的向下类型转换就是将向上转型的子类进行还原,还可执行子类中自己的方法。
子类中的构造过程
创建子类后,会首先调用父类中的默认构造方法,然后调用子类中的默认构造方法
如果在父类中写了一个有参构造,则无法调用父类中的默认构造方法,若创建对象会报错,有如下两种解决办法
1、该方法不常用
public class Daxiang extends Animal {
Daxiang(){
super("猴子",10);
}
protected String getName(){
return "大象";
}
}
在子类的默认构造中用super执行一下有参构造
2、在父类中定义默认构造,若一定要执行有参构造,则可把有参构造转换为函数方法在默认构造里使用
public class Animal{
private String name;
private int height;
public void Animal(String n, int h){
name = n;
height = h;
}
Animal(){
Animal("猴子", 1);
}
public void setName(String n){
name = n;
}
private String getName(){
return name;
}
}
一般来说都要父类中一定要写默认构造函数,放置发生子类构造时无法执行父类默认构造的情况。