Java语法-类和对象之继承与多态(中)

news2024/11/17 5:45:25

1. 继承

          为什么要继承?

                从生物学角度来说,继承就是把父辈的基因遗传给子代,然后子代再在细胞分裂的途中产生变异,生成比父辈更加适应环境的物种.其中很重要的就是继承给子代的基因(父类的方法和属性)和子代在父辈的基础上产生的变异(方法的重写). 比如猫和狗都是哺乳动物,是在哺乳动物的基础上发生进化和变异产生的独立的物种.它们都能吃饭和睡觉,但是他们的叫声不同.

      由该图可看出,猫和狗的类存在大量的重复,因此我们提出了继承的思想,专门用来进行共性的抽取,实现代码的复用.

        1.1 继承的概念

        继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特 性的基础上进行扩展,增加新功能,这样产生新的类,称派生类(子类)。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。
例如:狗和猫都是动物,那么我们就可以将共性的内容进行抽取,然后采用继承的思想来达到共用

上述图示中,Dog和Cat都继承了Animal类,其中:Animal类称为父类/基类或超类,Dog和Cat可以称为Animal的子类/派生类,继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可。

从继承概念中可以看出继承最大的作用就是:实现代码复用,还有就是来实现多态(后序讲)

        1.2 继承的语法

        我们使用extends关键字来实现继承

                修饰符 class 子类 extends 父类 {

                //具体内容}

        我们拿刚刚的猫和狗继承动物类的例子来说

//这个是父类
class Animal {
    //下面是俩个类共同的特点,我们把类的共性进行抽取,从而实现代码的复用效果
    //继承是 is a 的关系
    public String name;
    public int age;
    public void eat(){
        System.out.println(this.name+"正在吃饭!");
    }


    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("animal的构造方法");
    }
    static {
        System.out.println("animal的静态代码块");
    }
    {
        System.out.println("animal的实例代码块");
    }
}
//以下是动物类的子类
public class Dog extends Animal{
    public Dog(String name, int age) {
        super(name, age);
        System.out.println("Dog调用父类的构造方法,初始化成员");

    }


    public void bark(){
        System.out.println(this.name+"正在狗叫");
    }


 }

class Cat extends Animal{
     public Cat(String name, int age) {
         super(name, age);//这个是调用父类的有俩个参数的构造方法
         System.out.println("Cat调用父类的构造方法,初始化成员");
     }

     public void miao(){
         System.out.println(this.name+"正在猫叫");
     }
 

}

        1.3 访问父类和自己的成员变量和方法

                访问变量:

                如果父子类的变量名字不同,我们直接创建对象之后直接调用即可.

                如果父子类变量名字相同,那么我们优先调用子类的变量

                访问方法:

                成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错。

                我们来看一段代码:

class Animal {
    //下面是俩个类共同的特点,我们把类的共性进行抽取,从而实现代码的复用效果
    //继承是 is a 的关系
    public String name = "小黑";
    public int age;
    public void eat(){
        System.out.println(this.name+"正在吃饭!");
    }

    public Animal() {
        //无参构造方法
    }
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("animal的构造方法");
    }
  
    }
}
public class Dog extends Animal{
    public int id = 123;
    public String name = "小白";
    public Dog(String name, int age) {
        super(name, age);
        System.out.println("Dog调用父类的构造方法,初始化成员");

    }

    public Dog(String name, int age, int id) {
        super(name, age);
        this.id = id;
    }
    public Dog() {

    }

    public void bark(){
        System.out.println(this.name+"正在狗叫");
    }




    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println(dog.name);//直接访问继承下来的name
        System.out.println(dog.id);//直接访问dog自身的属性id
        dog.eat();//使用父类继承下来的eat方法
        dog.bark();//使用dog自身的bark方法


    }
}
//执行结果:
小白
123
小黑正在吃饭!
小白正在狗叫

          1.4 super关键字

           然后提出一个问题,我们该怎怎么在子类方法中访问父类的成员?

        super就出现了,该关键字主要作用:在子类方法中访问父类的成员。
 

public class Base {
int a;
int b;
public void methodA(){
System.out.println("Base中的methodA()");
}
public void methodB(){
System.out.println("Base中的methodB()");
}
}
public class Derived extends Base{
int a; // 与父类中成员变量同名且类型相同
char b; // 与父类中成员变量同名但类型不同
// 与父类中methodA()构成重载
public void methodA(int a) {
System.out.println("Derived中的method()方法");
} /
/ 与基类中methodB()构成重写(即原型一致,重写后序详细介绍)
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
// 对于同名的成员变量,直接访问时,访问的都是子类的
a = 100; // 等价于: this.a = 100;
b = 101; // 等价于: this.b = 101;
// 注意:this是当前对象的引用
// 访问父类的成员变量时,需要借助super关键字
// super是获取到子类对象中从基类继承下来的部分
super.a = 200;
super.b = 201;
// 父类和子类中构成重载的方法,直接可以通过参数列表区分清访问父类还是子类方法
methodA(); // 没有传参,访问父类中的methodA()
methodA(20); // 传递int参数,访问子类中的methodA(int)
// 如果在子类中要访问重写的基类方法,则需要借助super关键字
methodB(); // 直接访问,则永远访问到的都是子类中的methodA(),基类的无法访问到
super.methodB(); // 访问基类的methodB()
}
}

   【注意事项】

1. 只能在非静态方法中使用

2. 在子类方法中,访问父类的成员变量和方法。

        然后我们就可以根据super来构造子类的构造方法

package Class_Object.继承;


class Base {
    public int a = 3;
    public int c;

    public Base(int a, int c) {
        this.a = a;
        this.c = c;
    }

    public void method(){
        System.out.println("Base:method");
    }
}
class Derived extends Base {

    public int a = 10;
    public int b;

    public Derived(int a, int c) {
        super(a, c);
    }

    public void method(){
        System.out.println("Derived::method");
    }
    public void test() {
        super.method();//调用的是父类的方法
        this.method();//调用的是子类的方法
        System.out.println(this.a);
        System.out.println(a);
        System.out.println(super.a);
    }
}
public class Test {
    public static void main(String[] args) {
        Derived derived = new Derived(1,2);
        //super不能在静态方法使用
        //当子类和父类有同名的成员变量的时候,先看子类自己有没有,再看父类有没有
        derived.test();
    }


}
//Base:method
Derived::method
10
10
1

在子类构造方法中,并没有写任何关于基类构造的代码,但是在构造子类对象时,先执行基类的构造方法,然后执行子类的构造方法,因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整


        1.5 super和this的异同

super和this都可以在成员方法中用来访问:成员变量和调用其他的成员函数,都可以作为构造方法的第一条语句,那他们之间有什么区别呢?

        相同点:

        1. 都是Java中的关键字

        2. 只能在类的非静态方法中使用,用来访问非静态成员方法和字段

        3. 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在

        不同点:

        1. this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成

        2. 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性

         3. 在构造方法中:this(...)用于调用本类构造方法,super(...)用于调用父类构造方法,两种调用不能同时在构造 方法中出现

        4. 构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加,但是this(...)用户不写则没有员的引用

        1.6 再谈初始化

        在java类和对象(上)篇里面我们介绍了几个代码块,我们现在再把继承的思想融入进去,看运行结果有什么不同

        

package Class_Object.继承;

public class Dog extends Animal{
    public int id = 123;
    public String name = "小白";
    public Dog(String name, int age) {
        super(name, age);
        System.out.println("Dog调用父类的构造方法,初始化成员");

    }

    public Dog(String name, int age, int id) {
        super(name, age);
        this.id = id;
    }
    public Dog() {

    }

    public void bark(){
        System.out.println(this.name+"正在狗叫");
    }


    static {
        System.out.println("Dog的静态代码块");
    }
    {
        System.out.println("Dog的实例代码块");
    }

    public static void main(String[] args) {
//        Dog dog = new Dog();
//        System.out.println(dog.name);//直接访问继承下来的name
//        System.out.println(dog.id);//直接访问dog自身的属性id
//        dog.eat();//使用父类继承下来的eat方法
//        dog.bark();//使用dog自身的bark方法
        Dog dog = new Dog("小白",12);
        System.out.println("=============");
        Dog dog1 = new Dog("小黑",12);


    }
}
 class Cat extends Animal{
     public Cat(String name, int age) {
         super(name, age);//这个是调用父类的有俩个参数的构造方法
         System.out.println("Cat调用父类的构造方法,初始化成员");
     }

     public void miao(){
         System.out.println(this.name+"正在猫叫");
     }
     static {

     }

}
class Animal {
    //下面是俩个类共同的特点,我们把类的共性进行抽取,从而实现代码的复用效果
    //继承是 is a 的关系
    public String name = "小黑";
    public int age;
    public void eat(){
        System.out.println(this.name+"正在吃饭!");
    }

    public Animal() {
        //无参构造方法
    }
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("animal的构造方法");
    }
    static {
        System.out.println("animal的静态代码块");
    }
    {
        System.out.println("animal的实例代码块");
    }
}
//animal的静态代码块
Dog的静态代码块
animal的实例代码块
animal的构造方法
Dog的实例代码块
Dog调用父类的构造方法,初始化成员
=============
animal的实例代码块
animal的构造方法
Dog的实例代码块
Dog调用父类的构造方法,初始化成员

通过分析执行结果,得出以下结论:

        1、父类静态代码块优先于子类静态代码块执行,且是最早执行

        2、父类实例代码块和父类构造方法紧接着执行

        3、子类的实例代码块和子类构造方法紧接着再执行

        4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

        1.7 protected 关键字

        我们来填一下前面的坑

        protected里面如果一个父类里面一个变量被protected修饰,那么我们可以在另一个包里面创建一个类,继承这个父类,然后创建对象,就能够访问父类的变量

package Class_Object.继承;

public class Test1 {
    protected int a = 1999;//被protected修饰的变量
    final public void method(){
        System.out.println("这个是final不能被重写");
    }

}

package Class_Object.Protected;

import Class_Object.继承.Test1;

public class Test extends Test1 {//不同包的子类

    public void func() {
        System.out.println(super.a);//使用父类被protected修饰的变量
        //protected不同包中的子类
    }

    public static void main(String[] args) {
        Test test = new Test();
        test.func();
    }


}

}

        1.8 final关键字

        在引入final之前我们先聊一下继承的方式,在java中,继承只能是单继承,不支持多继承,而且一般我们不希望出现超过三层的继承关系,这时,我们就需要final关键字了.我们可以把final放在不希望被继承的类的访问修饰限定符前面如:final public class 类名{}

        final关键可以用来修饰变量、成员方法以及类。


        1. 修饰变量或字段,表示常量(即不能修改)

  final int a = 10; a = 20; // 编译出错


        2. 修饰类:表示此类不能被继承

final public class Animal {
...
}
public class Bird extends Animal {
...
} /
/ 编译出错
Error:(3, 27) java: 无法从最终com.bit.Animal进行继

     

package Class_Object.Protected;

import Class_Object.继承.Test1;

public class Test extends Test1 {

    public void func() {
        System.out.println(super.a);
        //protected不同包中的子类
    }

    public static void main(String[] args) {
        Test test = new Test();
        test.func();
    }

//
//    @Override
//    public void method() {
//        super.method();
//    }TODO 无法重写,因为final修饰父类的该方法,该方法变成了密封方法不能被重写
}
//TODO final的几种用法
final class TestFinall {//TODO 1.它这个类加了final表示当前类不能被继承了
    final int a = 10;//TODO 2.此时a就叫做常量,a只能初始化一次
//    a = 20;//
    //final表示不可变

}
//}
//class f extends TestFinall{
//
//}

  1.9 继承和组合的关系

        和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果。组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段。

继承表示对象之间是is-a的关系,比如:狗是动物

猫是动物组合表示对象之间是has-a的关系,比如:汽车

汽车和其轮胎、发动机、方向盘、车载系统等的关系就应该是组合,因为汽车是有这些部件组成的。
 

// 轮胎类
class Tire{
// ...
} /
/ 发动机类
class Engine{
// ...
} /
/ 车载系统类
class VehicleSystem{
// ...
}
class Car{
private Tire tire; // 可以复用轮胎中的属性和方法
private Engine engine; // 可以复用发动机中的属性和方法
private VehicleSystem vs; // 可以复用车载系统中的属性和方法
// ...
} /
/ 奔驰是汽车
class Benz extend Car{
// 将汽车中包含的:轮胎、发送机、车载系统全部继承下来
}

再比如学校,学校里面由学生和老师组成的:

package Class_Object.组合;

public class School {
    //组合是has a的关系
    public Student[] students;
    public Teacher[] teachers;
    int a;
    public School() {
        this.students = new Student[10];
        this.teachers = new Teacher[10];
        this.a = a;
    }
}
class Student{

}
class Teacher{

}

      差不多是这个意思: 把各个部件设置成一个类,然后把整体再设置一个类(框架),再在整体里面创建各个部件的类来填充这个类.

2.多态

        2.1 多态的概念

                简单来说就是多种形态,即:不同对象完成某个行为的时候会产生不同的状态.

比如:一个好看的小姐姐来和你搭话,你是一个好的态度,一个大老爷们来找你的时候你是另一个态度.

        总的来说:同一件事情,发生在不同对象身上,就会产生不同的结果


        2.2 多态的实现条件

                1. 要有继承关系(向上转型)

                2. 子类和父类有同名的 重写(覆盖) 方法

                3. 通过父类的引用 去调用这个重写方法

看个例子:

package Class_Object.多态;

class Animal {
    public String name;
    public int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void eat() {
        System.out.println(this.name+"正在吃东西");
    }
    public Animal test(){
        return null;
    }
}
class Dog extends Animal {

    public Dog(String name, int age) {
        super(name, age);
    }
    public void bark() {
        System.out.println(this.name + "狗叫");
    }
    @Override  //这个只是个注解 ctrl+o
    public void eat() {
        //在继承关系上,满足方法返回值,方法名字,方法的参数列表一致,那么就是方法的重写
        System.out.println(this.name+"正在吃狗粮");

    }
    @Override
    public Dog test(){
        return null;//这个返回值父类是父类类型,子类为子类类型
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
class Cat extends Animal {

    public Cat(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println(this.name + "正在吃猫粮");
    }

    @Override
    public Cat test() {
        return null;
    }
    public void miao() {
        System.out.println(this.name+"正在喵喵叫");
    }
}

public class Test {
    //向上转型
    //子类对象给父类
    public static void fuc(Animal animal) {
//TODO 传参进行向上转型
    }
    public static Dog fuc2(){
        Dog dog = new Dog("12",2);
        return dog;//TODO 返回值进行向上转型
    }

    public static void eatFunc(Animal animal) {
        animal.eat();//TODO 多态: 当父类引用 引用的子类对象不一样的时候,调用这个重写的方法,表现出来的行为是不一样的

}
    public static void main(String[] args) {
        Dog dog = new Dog("小白",9);
        Cat cat = new Cat("大白",89);
        eatFunc(dog);
        eatFunc(cat);


    }
    public static void main1(String[] args) {
        Dog dog = new Dog("小白",9);
        dog.eat();
        dog.bark();
        Animal animal1 = dog;//animal1这个引用指向了dog所指向的对象
        System.out.println("===========");
        Animal animal = new Dog("小黑",8);//TODO 直接引用
        animal.eat();
        fuc(dog);//这个也是向上转型
        Animal animal2 = fuc2();//这个也是向上转型
        animal.eat();//这个就是动态绑定,调用的时子类的eat(eat时父子类的重写方法)
        animal.test();//此时也是动态绑定(协变)
        System.out.println(dog);
        Animal animal3 = new Cat("大白",89);
    }
}

Animal是父类,Dog是子类,我们用父类的引用指向子类的对象,也就是:

父类 对象名 = new 子类(),然后我们再通过对象名来调用子类重写的父类的方法,这个过程就叫多态

        2.3 重写

        重写(override): 也称为覆盖.重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。

        【方法重写的规则】

        子类在重写父类的方法时,一般必须与父类方法原型一致: 返回值类型 方法名 (参数列表) 要完全一致.

        被重写的方法返回值类型可以不同,但是必须是具有父子关系

        访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方法就不能声明为 protected

        父类被static、private修饰的方法、构造方法都不能被重写。

        重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验. 例如不小心将方法名字拼写错了 (比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法构成重写.

        重写和重载的区别:

        方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现

        反正记住,重写只能改内容,其他不能改,构造方法一般不进行重写.

【重写的设计原则】

        对于已经投入使用的类,尽量不要进行修改。最好的方式是:重新定义一个新的类,来重复利用其中共性的内容,并且添加或者改动新的内容。

例如:若干年前的手机,只能打电话,发短信,来电显示只能显示号码,而今天的手机在来电显示的时候,不仅仅可以显示号码,还可以显示头像,地区等。在这个过程当中,我们不应该在原来老的类上进行修改,因为原来的类,可能还在有用户使用,正确做法是:新建一个新手机的类,对来电显示这个方法重写就好了,这样就达到了我们当今的需求了。

         然后我们聊聊静态绑定和动态绑定:

        静态绑定(前期绑定/早绑定): 比如你重载了一个方法再编译的时候,就会根据实参类中具体调用哪个方法

        动态绑定(后期绑定/晚绑定): 在编译的时候不能确定方法的行为(先调用父类的),需要等到程序运行时,才能确定具体调用哪个类的方法(再确定调用子类的)

        上次我们讲的toSting来打印对象就用到了方法的重载和动态绑定,

这个Object的toString(),注意Object是所有类的父类

 因此我们没有重写toString方法来直接调用object的toString方法:

就会出现这个类似地址的东西

但是如果我们重写了toString方法

        结果是:

然后我们就能够更好的理解重写了:重写就是为了扩充这个方法内部的实现功能.

        2.4 向上转型和向下转型:

        向上转型:实际就是创建一个子类对象,将其当成父类对象来使用。

        语法格式:父类类型 对象名 = new 子类类型()

        animal是父类类型,但可以引用一个子类对象,因为是从小范围向大范围的转换

        向上转型的优点:让代码实现更简单灵活。

        向上转型的缺陷:不能调用到子类特有的方法。

        将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象即可,即向下转换。
 

        向下转型: 父类引用再还原为子类对象

    

public class TestAnimal {
    public static void main(String[] args) {
        Cat cat = new Cat("元宝",2);
        Dog dog = new Dog("小七", 1);
// 向上转型
        Animal animal = cat;
        animal.eat();
        animal = dog;
        animal.eat();
// 编译失败,编译时编译器将animal当成Animal对象处理
// 而Animal类中没有bark方法,因此编译失败
// animal.bark();
// 向上转型
// 程序可以通过编程,但运行时抛出异常---因为:animal实际指向的是狗
// 现在要强制还原为猫,无法正常还原,运行时抛出:ClassCastException
        cat = (Cat)animal;
        cat.mew();
// animal本来指向的就是狗,因此将animal还原为狗也是安全的
        dog = (Dog)animal;
        dog.bark();
    }
}

向下转型用的比较少,而且不安全,万一转换失败,运行时就会抛异常。Java中为了提高向下转型的安全性,引入了 instanceof ,如果该表达式为true,则可以安全转换。
 

public class TestAnimal {
    public static void main(String[] args) {
        Cat cat = new Cat("元宝", 2);
        Dog dog = new Dog("小七", 1);
// 向上转型
        Animal animal = cat;
        animal.eat();
        animal = dog;
        animal.eat();
        if (animal instanceof Cat) {
            cat = (Cat) animal;
            cat.mew();
        }
        if (
                animal instanceof Dog) {
            dog = (Dog) animal;
            dog.bark();
        }
    }
}

        2.5 多态的实际用例:

        我们学习到这里应该已经了解了继承和多态的使用,现在写一个例子

package Class_Object.多态的应用;

abstract public class Shape {//这是个抽象类,后面下一节会讲,现在单纯理解为一个父类

    abstract public void draw();
}
class Rect extends Shape {
    @Override
    public void draw() {
        System.out.println("矩形");//重写draw方法
    }
}
class Triangle extends Shape{

    @Override
    public void draw() {
        System.out.println("三角形");//重写draw方法
    }
}
class Cycle extends Shape {
    @Override
    public void draw() {

        System.out.println("圆形");//重写draw方法
    }
}

    public static void main(String[] args) {//这个是法2
        Shape[] shapes = {new Cycle(),new Triangle(),new Rect()};//造一个shape数组,然后直接在里面new 它的子类对象
        for (Shape shape:shapes) {
            shape.draw();//直接for循环,循环到哪个就调用哪个draw方法
        }
    }
    public static void main1(String[] args) {//这个是法1
        Cycle cycle = new Cycle();
        Rect rect = new Rect();
        Triangle triangle = new Triangle();
        String[] strings = {"cycle","rect","triangle"};
        for (String x:strings){
            if(x.equals("cycle")) {
                cycle.draw();
            } else if (x.equals("rect")) {
                rect.draw();
            } else if (x.equals("triangle")) {
                triangle.draw();
            }//但是if else的大量使用会造成圈复杂度太高
        }

    }
}

看到法1我们发现圈复杂度太高(使用大量的 if - else)不利于开发

并且法二有利于对扩展

如果要新增一种新的形状, 使用多态的方式代码改动成本也比较低
 

class Triangle extends Shape {
@Override
public void draw() {
System.out.println("△");
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2168375.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

刷题小记3----每日一题精进Java技能(详细思路解析✅)

文章目录 一、两种排序方法二、最小公倍数三、另类加法四、倒置字符串五、统计回文 一、两种排序方法 题目链接:两种排序方法 题目描述: 考拉有n个字符串字符串,任意两个字符串长度都是不同的。考拉最近学习到有两种字符串的排序方法&#x…

相亲交友系统软件大比拼

在当今社会,相亲交友系统已成为许多单身人士寻找理想伴侣的重要途径之一。随着技术的发展,各种相亲交友软件层出不穷,它们各自拥有独特的特色和服务模式。今天,我们将对几款热门的相亲交友系统软件进行一番大比拼,看看…

技术成神之路:设计模式(十六)代理模式

介绍 代理模式(Proxy Pattern)是一种结构性设计模式,它通过代理对象来控制对另一个对象的访问。代理对象在功能上与真实对象相似,但可以在访问真实对象前后添加一些额外的处理。代理模式常用于控制对某个对象的访问、延迟实例化、…

【隐私计算篇】利用多方安全计算MPC实现VGG16人脸识别隐私推理

1. 背景介绍 本文主要介绍一种利用多方安全计算MPC技术,实现VGG16的人脸识别模型,侧重于模型推理阶段,目前已经公开专利,因此以下内容的分享都是基于公开材料。该分享涉及到最小化多方安全计算(MPC)以及明密文混合计算的思想&…

【Python报错已解决】TypeError: tuple indices must be integers or slices, not str

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 专栏介绍 在软件开发和日常使用中,BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

??实验——完全使用Ansible部署多台服务器的服务

文章目录 需求两台Web服务器部署同一Web应用WeCenter,且两台服务器的用户上传的数据目录挂载到共享存储服务器中,总数据保存在一台数据库服务器中使用sersync简单实现两台共享存储服务器之间的Web应用共享数据目录的数据同步每天定时将两台Web服务器的We…

高效检测围栏翻越的视觉分析算法

随着社会安全防范需求的不断增加,围栏作为重要的防护手段,被广泛应用于公共场所、工业园区、住宅区等区域。然而,传统的围栏虽然能起到一定的阻隔作用,却无法有效监控和防止人为的翻越行为。近年来,智能监控技术的兴起…

828华为云征文|Flexus云服务器X实例实践:安装SimpleMindMap思维导图工具

828华为云征文|Flexus云服务器X实例实践:安装Ward服务器监控工具 引言一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 主要使用场景 二、购买Flexus云服务器X实例2.1 购买规格参考2.2 查看Flexus云服务器X实例状态 三、远程连接Flexus云服务…

C++类和对象——第二关

目录 类的默认成员函数: (一)构造函数 (二)析构函数 (三)拷贝构造函数 类的默认成员函数: 类里面有6个特殊的成员函数分别包揽不同的功能; (一)构造函数…

基于nodejs+vue的小型企业工资管理系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏:Java精选实战项目…

[附源码]在线音乐系统+SpringBoot+Vue前后端分离

今天带来一款优秀的项目:在线音乐系统源码 。 系统采用的流行的前后端分离结构,内含功能包括 "管理后台",“用户端”,“评论系统”,“歌手,歌曲管理”,“用户系统”,"统计"…

mapboxGL 离线部署或者说去除token最简单得方法

找到本项目中得node_modules包管理器中得mapbox-gl包 找打dist文件夹下得mapbox-gl-dev.js 相比于mapbox-gl.js得压缩文件 mapbox-gl-dev.js没有压缩,好修改,也无需要编译 在mapbox-gl-dev.js找到 this._authenticate(),注释或者去除即可 最…

tauri中加载本地文件图片或者下载网络文件图片后存储到本地,然后通过前端页面展示

有一个需求是需要将本地上传的文件或者网络下载的文件存储到本地,并展示在前端页面上的。其实如果只是加载本地文件,然后展示还是挺简单的,可以看我的文章:tauri程序加载本地图片或者文件在前端页面展示-CSDN博客 要想实现上述需…

【Linux】项目自动化构建工具-make/Makefile 详解

🔥 个人主页:大耳朵土土垚 🔥 所属专栏:Linux系统编程 这里将会不定期更新有关Linux的内容,欢迎大家点赞,收藏,评论🥳🥳🎉🎉🎉 文章目…

关于车载视频监控的重要性及其发展趋势

一、车载视频监控的意义和概念 车载视频监控是专为车载安防领域打造的一款新型视频监控设备。随着社会的快速发展和科技的不断进步,安装车载视频监控设备已经成为社会发展的必然趋势。车载视频监控不仅关乎个人安全,更对企业的安全生产和管理起着至关重要…

可编辑PPT | 能源企业数字化框架、数字化运营及数字化平台建设方案

项目背景及需求理解 首先提出了全球能源互联网的概念,强调了清洁能源和电能替代的重要性,并介绍了德国工业4.0战略以及泛在电力物联网的创新。文档探讨了信息化与工业化的深度融合,以及云计算、大数据、物联网和移动应用等新技术在能源行业的…

克隆GitHub仓库中的一个文件夹

要只克隆GitHub仓库中的一个文件夹&#xff0c;你可以使用 git sparse-checkout 功能。以下是具体步骤&#xff1a; 克隆仓库&#xff08;使用 --no-checkout 选项&#xff0c;避免下载所有内容&#xff09;&#xff1a; git clone --no-checkout <仓库地址> 进入克隆的…

微信小程序组件封装使用

1.第一步先新建一个components组件的文件夹第二步在创建一个文件夹第三步在新建components 例如先封装一个VCaption头部导航组件

IvorySQL 3.4 来了

9 月 26 日&#xff0c;IvorySQL 3.4 发版。本文将带大家快速了解新版本特性。 IvorySQL 3.4 发版说明 IvorySQL 3.4 基于 PostgreSQL 16.4&#xff0c;修复了多个问题&#xff0c;并增强多项功能。 PostgreSQL 16.4 的变更 在未经授权时防止 pg_dump 执行&#xff0c;并引入一…

初识C语言(三)

感兴趣的朋友们可以留个关注&#xff0c;我们共同交流&#xff0c;相互促进学习。 文章目录 前言 八、函数 九、数组 &#xff08;1&#xff09;数组的定义 &#xff08;2&#xff09;数组的下标和使用 十、操作符 &#xff08;1&#xff09;算数操作符 &#xff08;2&#xff…