当前位置:首页 > 后端开发 > 正文内容

Scala面向对象

邻居的猫1个月前 (12-09)后端开发975

类和目标

组成结构
• 结构函数: 在创立目标的时分给特点赋值
• 成员变量:
• 成员办法(函数)
• 局部变量
• 代码块

结构器

每个类都有一个主结构器,这个结构器和类界说"交错"在一起类名后边的内容便是主结构器,假如参数列表为空的话,()能够省掉
scala的类有且仅有一个主结构器,要想供给愈加丰厚的结构器,就需求运用辅佐结构器,辅佐结构器是可选的,它们叫做this def this
留意:主结构器会履行类界说中的一切句子
代码示例:

// 类默许有一个无参的主结构函数
class User { 
}

val user: User = new User

// 两个参数的主结构函数
class User2(val name: String, age: Int) { 

}
val user2 = new User2("jim", 23)
// 运用val润饰的变量默许是成员变量,目标能够拜访
// user2.age   // age没有运用val或许var润饰 所以不能被拜访,他不是一个成员变量,而是一个局部变量


//辅佐结构器
class User3 {
   var name: String = _
   var age: Int = _
  // 辅佐结构函数
  def this(name: String, age: Int) {
    // 结构函数中的首行有必要调用主结构函数或许其他结构函数
    this()
    this.name = name
    this.age = age
  }
  // 辅佐结构函数
  def this(msg: String) = {
    // 首行调用一个结构
    this("ww", 12)
    println(msg)
  }
}
val u1 = new User3()
val u2 = new User3("")
val u3 = new User3("lisi", 23)
println(u3.name)

总结:

  1. 有两类结构器:主结构器,辅佐结构器
  2. 结构器的界说方位:主结构器和类交错在一起,class Student2(val name: String, var age: Int)
  3. 辅佐结构器是一个特其他办法,界说在类中 def this(name:String,age:Int,gender:String)
  4. 辅佐结构器,榜首行有必要调用主结构器(或许其他的辅佐结构器)
  5. 辅佐结构器的参数不能和主结构器的参数完全共同(参数个数,参数类型,参数次序)
  6. 能够界说空参的辅佐结构器,可是主结构器的参数有必要进行初始化赋值
  7. 作用域:辅佐结构器的变量作用域,只在办法中,主结构器的作用域是类中除了成员特点和成员办法之外的一切规模(能够经过反编译检查源码)

结构器的参数阐明

  • 主结构函数中运用val 和 var润饰的变量为成员变量
  • val 润饰的变量默许只要getter办法 一要初始化
  • var 润饰的变量默许有 get和set办法 直接点特点操作 运用 _ 占位能够稍后赋值
  • @BeanProperty会生成getMsg setMsg办法

成员办法/函数

在类的成员方位界说的函数或许办法是类的成员的一部分

代码块

在类或许目标中的代码块在实例化的时分会被调用

  • 在类成员方位的代码块 结构代码块 每次创立目标都会履行一次
  • 在object中成员方位的代码块是静态代码块 只履行一次
  • 代码有返回值

object类的底层原理

package com.doit.day01.day02

//假如结构器中的变量,不加var 或许val 那他便是一个局部变量
//加了var 或许val 的话他便是一个私有的成员变量
class Student1(var id: Int, val name: String) {

  def sayHello: Unit = {
    println(name + ":你好")
  }

  val sayFunc = () => {
    println("hello:" + name)
  }
}


object Student2{
  var id: Int = 1
  //假如在成员变量的方位上给一个_作为占位符,适当所以给他赋了一个默许值啊
  var name: String =_

  def sayHello: Unit = {
    println(name + ":你好")
  }
  val sayFunc = (x:String) => {
    println("hello:" + name + x)
  }
}


object Demo01_面向目标 {
  def main(args: Array[String]): Unit = {

    Student2.sayFunc("a")

    val student1: Student1 = new Student1(1, "zhangsan")
    println(student1.name)
    println(student1.id)
    //    student1.name = "lisi"  用val 润饰的,不能修正
    student1.id = 2
    println(student1.id)

    student1.sayHello
    student1.sayFunc()
    println(Student2.name)
  }
}

java手写完成:

package com.doit;


public class Person {
    public static String getName(){
        return Person$.person.getName();
    }

    public static Integer getAge(){
        return Person$.person.getAge();
    }

    public static void setName(String name ){
        Person$.person.setName(name);
    }

    public static void setAge(Integer age ){
        Person$.person.setAge(age);
    }
}

class Person$ {
    //自己的目标
    public static Person$ person ;
    //成员变量
    private String name;
    private int age;

    static {
        person  = new Person$();
    }

    private Person$() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}


class Test{
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("张三");
        person.setAge(18);
        String name1 = person.getName();
        Integer age1 = person.getAge();
        System.out.println(name1);
        System.out.println(age1);
    }
}

scala中底层反编译后的代码:

package com.doit.day01.day02;

import java.lang.invoke.SerializedLambda;
import scala.Function1;
import scala.Predef.;
import scala.runtime.BoxedUnit;

public final class Student2$ {
   public static Student2$ MODULE$;
   private int id;
   private String name;
   private final Function1 sayFunc;

   static {
      new Student2$();
   }

   public int id() {
      return this.id;
   }

   public void id_$eq(final int x$1) {
      this.id = x$1;
   }

   public String name() {
      return this.name;
   }

   public void name_$eq(final String x$1) {
      this.name = x$1;
   }

   public void sayHello() {
      .MODULE$.println((new StringBuilder(3)).append(this.name()).append(":你好").toString());
   }

   public Function1 sayFunc() {
      return this.sayFunc;
   }

// $FF: synthetic method
   public static final void $anonfun$sayFunc$1(final String x) {
      .MODULE$.println((new StringBuilder(6)).append("hello:").append(MODULE$.name()).append(x).toString());
   }

   private Student2$() {
      MODULE$ = this;
      this.id = 1;
      this.sayFunc = (x) -> {
         $anonfun$sayFunc$1(x);
         return BoxedUnit.UNIT;
      };
   }

// $FF: synthetic method
   private static Object $deserializeLambda$(SerializedLambda var0) {
      return var0.lambdaDeserialize<invokedynamic>(var0);
   }
}

 //decompiled from Student2.class
package com.doit.day01.day02;

import scala.Function1;
import scala.reflect.ScalaSignature;

@ScalaSignature(
   bytes = "\u0006\u0001!;Q\u0001D\u0007\t\u0002Y1Q\u0001G\u0007\t\u0002eAQ\u0001I\u0001\u0005\u0002\u0005BqAI\u0001A\u0002\u0013\u00051\u0005C\u0004(\u0003\u0001\u0007I\u0011\u0001\u0015\t\r9\n\u0001\u0015)\u0003%\u0011%y\u0013\u00011AA\u0002\u0013\u0005\u0001\u0007C\u0005=\u0003\u0001\u0007\t\u0019!C\u0001{!Iq(\u0001a\u0001\u0002\u0003\u0006K!\r\u0005\u0006\u0001\u0006!\t!\u0011\u0005\b\u0005\u0006\u0011\r\u0011\"\u0001D\u0011\u00199\u0015\u0001)A\u0005\t\u0006A1\u000b^;eK:$(G\u0003\u0002\u000f\u001f\u0005)A-Y=1e)\u0011\u0001#E\u0001\u0006I\u0006L\b'\r\u0006\u0003%M\tA\u0001Z8ji*\tA#A\u0002d_6\u001c\u0001\u0001\u0005\u0002\u0018\u00035\tQB\u0001\u0005TiV$WM\u001c;3'\t\t!\u0004\u0005\u0002\u001c=5\tADC\u0001\u001e\u0003\u0015\u00198-\u00197b\u0013\tyBD\u0001\u0004B]f\u0014VMZ\u0001\u0007y%t\u0017\u000e\u001e \u0015\u0003Y\t!!\u001b3\u0016\u0003\u0011\u0002\"aG\u0013\n\u0005\u0019b\"aA%oi\u00061\u0011\u000eZ0%KF$\"!\u000b\u0017\u0011\u0005mQ\u0013BA\u0016\u001d\u0005\u0011)f.\u001b;\t\u000f5\"\u0011\u0011!a\u0001I\u0005\u0019\u0001\u0010J\u0019\u0002\u0007%$\u0007%\u0001\u0003oC6,W#A\u0019\u0011\u0005IJdBA\u001a8!\t!D$D\u00016\u0015\t1T#\u0001\u0004=e>|GOP\u0005\u0003qq\ta\u0001\u0015:fI\u00164\u0017B\u0001\u001e<\u0005\u0019\u0019FO]5oO*\u0011\u0001\bH\u0001\t]\u0006lWm\u0018\u0013fcR\u0011\u0011F\u0010\u0005\b[\u001d\t\t\u00111\u00012\u0003\u0015q\u0017-\\3!\u0003!\u0019\u0018-\u001f%fY2|W#A\u0015\u0002\u000fM\f\u0017PR;oGV\tA\t\u0005\u0003\u001c\u000bFJ\u0013B\u0001$\u001d\u0005%1UO\\2uS>t\u0017'\u0001\u0005tCf4UO\\2!\u0001"
)
public final class Student2 {
   public static Function1 sayFunc() {
      return Student2$.MODULE$.sayFunc();
   }

   public static void sayHello() {
      Student2$.MODULE$.sayHello();
   }

   public static void name_$eq(final String x$1) {
      Student2$.MODULE$.name_$eq(var0);
   }

   public static String name() {
      return Student2$.MODULE$.name();
   }

   public static void id_$eq(final int x$1) {
      Student2$.MODULE$.id_$eq(var0);
   }

   public static int id() {
      return Student2$.MODULE$.id();
   }
}

伴生类和伴生目标

条件 1:在同一个源文件中, 条件 2:目标名和类名相同

  //类名和object的称号共同
  //类是目标的伴生类
  //目标是类的伴生目标

class Demo6(val name: String) {
}
object Demo6 {
}

条件 2:伴生目标和伴生类之间能够相互拜访互相的私有特点和私有办法

package com.doit.day01.day02

/**
 * 伴生目标的用处:
 *      1.能够将静态的成员变量和一般成员变量别离声明
 *      2.伴生目标自己内部界说了一个apply办法,能够简化创立目标(类的实例结构)
 *      3.伴生目标自己界说了一个unapply办法,能够用于形式匹配
 */
class Car(var brand: String, var price: Double) {

  def sayHello(): Unit ={
    println("hello")
  }

  private val color: String = Car.color
  Car.start()
}


object Car {
  var color :String = "red"

  def start(): Unit ={
    println("轿车启动了,嗡~~~~~~~~")
  }
}

object Demo02_伴生目标 {
  def main(args: Array[String]): Unit = {
    val car: Car = new Car("华为", 9.9)
    println(car.brand)
    println(car.price)
    car.sayHello()
    Car.start()
  }
}

伴生目标的底层原理:

//decompiled from Car.class
package com.doit.day01.day02;

import scala.Predef.;
import scala.reflect.ScalaSignature;

@ScalaSignature(
   bytes = "\u0006\u0001E3A\u0001E\t\u00015!A\u0011\u0005\u0001BA\u0002\u0013\u0005!\u0005\u0003\u0005/\u0001\t\u0005\r\u0011\"\u00010\u0011!)\u0004A!A!B\u0013\u0019\u0003\u0002\u0003\u001c\u0001\u0005\u0003\u0007I\u0011A\u001c\t\u0011m\u0002!\u00111A\u0005\u0002qB\u0001B\u0010\u0001\u0003\u0002\u0003\u0006K\u0001\u000f\u0005\u0006\u007f\u0001!\t\u0001\u0011\u0005\u0006\u000b\u0002!\tAR\u0004\u0006\u000fFA\t\u0001\u0013\u0004\u0006!EA\t!\u0013\u0005\u0006\u007f)!\tA\u0013\u0005\b\u0017*\u0001\r\u0011\"\u0001#\u0011\u001da%\u00021A\u0005\u00025Caa\u0014\u0006!B\u0013\u0019\u0003\"\u0002)\u000b\t\u00031%aA\"be*\u0011!cE\u0001\u0006I\u0006L\bG\r\u0006\u0003)U\tQ\u0001Z1zaER!AF\f\u0002\t\u0011|\u0017\u000e\u001e\u0006\u00021\u0005\u00191m\\7\u0004\u0001M\u0011\u0001a\u0007\t\u00039}i\u0011!\b\u0006\u0002=\u0005)1oY1mC&\u0011\u0001%\b\u0002\u0007\u0003:L(+\u001a4\u0002\u000b\t\u0014\u0018M\u001c3\u0016\u0003\r\u0002\"\u0001J\u0016\u000f\u0005\u0015J\u0003C\u0001\u0014\u001e\u001b\u00059#B\u0001\u0015\u001a\u0003\u0019a$o\\8u}%\u0011!&H\u0001\u0007!J,G-\u001a4\n\u00051j#AB*ue&twM\u0003\u0002+;\u0005I!M]1oI~#S-\u001d\u000b\u0003aM\u0002\"\u0001H\u0019\n\u0005Ij\"\u0001B+oSRDq\u0001\u000e\u0002\u0002\u0002\u0003\u00071%A\u0002yIE\naA\u0019:b]\u0012\u0004\u0013!\u00029sS\u000e,W#\u0001\u001d\u0011\u0005qI\u0014B\u0001\u001e\u001e\u0005\u0019!u.\u001e2mK\u0006I\u0001O]5dK~#S-\u001d\u000b\u0003auBq\u0001N\u0003\u0002\u0002\u0003\u0007\u0001(\u0001\u0004qe&\u001cW\rI\u0001\u0007y%t\u0017\u000e\u001e \u0015\u0007\u0005\u001bE\t\u0005\u0002C\u00015\t\u0011\u0003C\u0003\"\u000f\u0001\u00071\u0005C\u00037\u000f\u0001\u0007\u0001(\u0001\u0005tCfDU\r\u001c7p)\u0005\u0001\u0014aA\"beB\u0011!IC\n\u0003\u0015m!\u0012\u0001S\u0001\u0006G>dwN]\u0001\nG>dwN]0%KF$\"\u0001\r(\t\u000fQj\u0011\u0011!a\u0001G\u000511m\u001c7pe\u0002\nQa\u001d;beR\u0004"
)
public class Car {
   private String brand;
   private double price;

   public static void start() {
      Car$.MODULE$.start();
   }

   public static void color_$eq(final String x$1) {
      Car$.MODULE$.color_$eq(var0);
   }

   public static String color() {
      return Car$.MODULE$.color();
   }

   public String brand() {
      return this.brand;
   }

   public void brand_$eq(final String x$1) {
      this.brand = x$1;
   }

   public double price() {
      return this.price;
   }

   public void price_$eq(final double x$1) {
      this.price = x$1;
   }

   public void sayHello() {
      .MODULE$.println("hello");
   }

   public Car(final String brand, final double price) {
      this.brand = brand;
      this.price = price;
      super();
   }
}

        //decompiled from Car$.class
package com.doit.day01.day02;

import scala.Predef.;

public final class Car$ {
   public static Car$ MODULE$;
   private String color;

   static {
      new Car$();
   }

   public String color() {
      return this.color;
   }

   public void color_$eq(final String x$1) {
      this.color = x$1;
   }

   public void start() {
      .MODULE$.println("轿车启动了,嗡~~~~~~~~");
   }

   private Car$() {
      MODULE$ = this;
      this.color = "red";
   }
}

图示:

image
伴生目标用处:

  1. 能够将静态的成员变量和一般成员变量别离声明(class中没办法添加静态成员,需求经过object类来添加)
  2. 伴生目标自己内部界说了一个apply办法,能够简化创立目标(类的实例结构)
  3. 伴生目标自己界说了一个unapply办法,能够用于形式匹配

apply办法

运用此办法时,能够在main函数中不经过new来创立一个目标,即能够不必专门的一次一次地进行实例化,加载创立目标的这个类的时分,会主动调用apply这个办法,相似Java中的static静态块。

  1. 经过伴生目标的 apply 办法,完成不运用 new 办法创立目标。
  2. apply 办法能够重载。
  3. Scala 中 obj(arg)的句子实践是在调用该目标的 apply 办法,即 obj.apply(arg)。用以一致面向目标编程和函数式编程的风格。
  4. 当运用 new 关键字构建目标时,调用的其实是类的结构办法,当直接运用类名构建目标时,调用的其实是伴生目标的 apply 办法。
object Test {
 def main(args: Array[String]): Unit = {
 //(1)经过伴生目标的 apply 办法,完成不运用 new 关键字创立目标。
 val p1 = Person()
 println("p1.name=" + p1.name)
 val p2 = Person("bobo")
 println("p2.name=" + p2.name)
 } 
}
//(2)假如想让主结构器变成私有的,能够在()之前加上 private
class Person private(cName: String) {
 var name: String = cName
}

object Person {
 def apply(): Person = {
 println("apply 空参被调用")
 new Person("xx")
 }
 
 def apply(name: String): Person = {
 println("apply 有参被调用")
 new Person(name)
}
}

权限润饰符

在 Java 中,拜访权限分为:public,private,protected 和默许。在 Scala 中,你能够经过相似的润饰符到达相同的作用。可是运用上有差异。
(1)Scala 中特点和办法的默许拜访权限为 public,但 Scala 中无 public 关键字。
(2)private 为私有权限,只在类的内部和伴生目标中可用。
(3)protected 为受维护权限,Scala 中受维护权限比 Java 中更严厉,同类、子类能够拜访,同包无法拜访。
(4)private[包名]添加包拜访权限,包名下的其他类也能够运用
代码演示:

class Person {
 private var name: String = "bobo"
 protected var age: Int = 18
 private[test] var sex: String = "男"
 def say(): Unit = {
 println(name)
 } 
}
object Person {
 def main(args: Array[String]): Unit = {
 val person = new Person
 person.say()
 println(person.name)
 println(person.age)
 } 
}
class Teacher extends Person {
 def test(): Unit = {
 this.age
 this.sex
 } 
}
class Animal {
 def test: Unit = {
 new Person().sex
 }
}

特质和笼统类

特质

Trait(特质)适当于 java 的接口。比接口功用更强壮。特质中能够界说特点和笼统办法和办法的完成。
Scala 的类只能够承继单一父类,可是能够完成(承继,混入)多个特质(Trait),运用的关键字是 with 和 extends
留意,特质不能有主结构函数
根本语法

trait 特质名 {
trait 主体
} 

怎么运用特质:
没有父类:class 类名 extends 特质 1 with 特质 2 with 特质 3 …
有父类:class 类名 extends 父类 with 特质 1 with 特质 2 with 特质 3…
代码演示:

trait PersonTrait {
 // 声明特点
 var name:String = _
 // 声明办法
 def eat():Unit={
 }
 // 笼统特点
 var age:Int
 
 // 笼统办法
 def say():Unit
}

特质的实质便是笼统类+接口

特质的动态混入

1.创立目标时混入 trait,而无需使类混入该 trait
2.假如混入的 trait 中有未完成的办法,则需求完成
代码演示:

trait PersonTrait {
 //(1)特质能够一起具有笼统办法和详细办法
 // 声明特点
 var name: String = _
 // 笼统特点
 var age: Int
 // 声明办法
 def eat(): Unit = {
 println("eat")
 }
 // 笼统办法
 def say(): Unit
}
trait SexTrait {
 var sex: String
}
//(2)一个类能够完成/承继多个特质
//(3)一切的 Java 接口都能够作为 Scala 特质运用
class Teacher extends PersonTrait with java.io.Serializable {
 override def say(): Unit = {
 println("say")
 }
 override var age: Int = _
}
object TestTrait {
 def main(args: Array[String]): Unit = {
 val teacher = new Teacher
 teacher.say()
 teacher.eat()
 //(4)动态混入:可灵敏的扩展类的功用
 val t2 = new Teacher with SexTrait {
 override var sex: String = "男"
 }
 //调用混入 trait 的特点
 println(t2.sex)
 } 
}

笼统类

在 Scala 中, 运用 abstract 润饰的类称为笼统类. 在笼统类中能够界说特点、未完成的办法(笼统办法)和详细完成的办法。 含有笼统办法的类便是笼统类

  • 笼统类中的特点
  • 笼统办法
  • 详细完成的办法
  • 类的单承继

示例:

/*
* abstract 润饰的类是一个笼统类
* */
abstract class Animal {
  println("Animal's constructor ....")
  // 界说一个 name 特点
  val name: String = "animal"
  // 没有任何完成的办法
  def sleep()
  // 带有详细的完成的办法
  def eat(f: String): Unit = {
    println(s"$f")
    }
  }

笼统类的承继和重写

  • 假如父类为笼统类,那么子类要么也是笼统类,要么就需求重写父类中的一切的笼统办法和笼统的成员变量
  • 重写非笼统办法需求用 override 润饰,重写笼统办法则能够不加 override。
  • 子类中调用父类的办法运用 super 关键字,在子类重写了父类的办法后,假如不加super,直接写办法名调用的便是子类重写后的,假如加了,调用的仍是父类的
  • 子类对笼统特点进行完成,父类笼统特点能够用 var 润饰;子类对非笼统特点重写,父类非笼统特点只支撑 val 类型,而不支撑 var(var润饰详细办法和变量欠好重写)

由于 var 润饰的为可变变量,子类承继之后就能够直接运用,没有必要重写

样例类

运用case润饰的类便是样例类(封装数据,形式匹配)

  1. 结构器中的参数默许是val润饰的[成员,赋值1次]
  2. 样例类会主动创立伴生目标, 一起在里面完成;的apply和unapply办法 ,创立目标的时分不必new
  3. 很好的支撑匹配形式
  4. 默许完成了自己的toString , hashCode , copy , equals,序列化办法

界说一个样例类:

case class Person(var name:String , var age:Int){}
//假如类中没有其他需求界说的,能够不写大括号

反编译之后的成果:

//decompiled from Person$.class
package com.doit.day01.day02;

import scala.Option;
import scala.Serializable;
import scala.Some;
import scala.Tuple2;
import scala.None.;
import scala.runtime.AbstractFunction2;
import scala.runtime.BoxesRunTime;

public final class Person$ extends AbstractFunction2 implements Serializable {
   public static Person$ MODULE$;

   static {
      new Person$();
   }

   public final String toString() {
      return "Person";
   }

   public Person apply(final String name, final int age) {
      return new Person(name, age);
   }

   public Option unapply(final Person x$0) {
      return (Option)(x$0 == null ? .MODULE$ : new Some(new Tuple2(x$0.name(), BoxesRunTime.boxToInteger(x$0.age()))));
   }

   private Object readResolve() {
      return MODULE$;
   }

   // $FF: synthetic method
   // $FF: bridge method
   public Object apply(final Object v1, final Object v2) {
      return this.apply((String)v1, BoxesRunTime.unboxToInt(v2));
   }

   private Person$() {
      MODULE$ = this;
   }
}

        //decompiled from Person.class
package com.doit.day01.day02;

import scala.Function1;
import scala.Option;
import scala.Product;
import scala.Serializable;
import scala.collection.Iterator;
import scala.reflect.ScalaSignature;
import scala.runtime.BoxesRunTime;
import scala.runtime.Statics;
import scala.runtime.ScalaRunTime.;

@ScalaSignature(
   bytes = "\u0006\u0001\u0005Uc\u0001\u0002\u000e\u001c\u0001\u0012B\u0001\"\r\u0001\u0003\u0012\u0004%\tA\r\u0005\t}\u0001\u0011\t\u0019!C\u0001\u007f!AQ\t\u0001B\tB\u0003&1\u0007\u0003\u0005G\u0001\tE\r\u0011\"\u0001H\u0011!Y\u0005A!a\u0001\n\u0003a\u0005\u0002\u0003(\u0001\u0005#\u0005\u000b\u0015\u0002%\t\u000b=\u0003A\u0011\u0001)\t\u000fU\u0003\u0011\u0011!C\u0001-\"9\u0011\fAI\u0001\n\u0003Q\u0006bB3\u0001#\u0003%\tA\u001a\u0005\bQ\u0002\t\t\u0011\"\u0011j\u0011\u001d\t\b!!A\u0005\u0002\u001dCqA\u001d\u0001\u0002\u0002\u0013\u00051\u000fC\u0004y\u0001\u0005\u0005I\u0011I=\t\u0013\u0005\u0005\u0001!!A\u0005\u0002\u0005\r\u0001\"CA\u0007\u0001\u0005\u0005I\u0011IA\b\u0011%\t\t\u0002AA\u0001\n\u0003\n\u0019\u0002C\u0005\u0002\u0016\u0001\t\t\u0011\"\u0011\u0002\u0018\u001dI\u00111D\u000e\u0002\u0002#\u0005\u0011Q\u0004\u0004\t5m\t\t\u0011#\u0001\u0002 !1q\n\u0006C\u0001\u0003[A\u0011\"!\u0005\u0015\u0003\u0003%)%a\u0005\t\u0013\u0005=B#!A\u0005\u0002\u0006E\u0002\"CA\u001c)\u0005\u0005I\u0011QA\u001d\u0011%\tY\u0005FA\u0001\n\u0013\tiE\u0001\u0004QKJ\u001cxN\u001c\u0006\u00039u\tQ\u0001Z1zaIR!AH\u0010\u0002\u000b\u0011\f\u0017\u0010M\u0019\u000b\u0005\u0001\n\u0013\u0001\u00023pSRT\u0011AI\u0001\u0004G>l7\u0001A\n\u0005\u0001\u0015Zc\u0006\u0005\u0002'S5\tqEC\u0001)\u0003\u0015\u00198-\u00197b\u0013\tQsE\u0001\u0004B]f\u0014VM\u001a\t\u0003M1J!!L\u0014\u0003\u000fA\u0013x\u000eZ;diB\u0011aeL\u0005\u0003a\u001d\u0012AbU3sS\u0006d\u0017N_1cY\u0016\fAA\\1nKV\t1\u0007\u0005\u00025w9\u0011Q'\u000f\t\u0003m\u001dj\u0011a\u000e\u0006\u0003q\r\na\u0001\u0010:p_Rt\u0014B\u0001\u001e(\u0003\u0019\u0001&/\u001a3fM&\u0011A(\u0010\u0002\u0007'R\u0014\u0018N\\4\u000b\u0005i:\u0013\u0001\u00038b[\u0016|F%Z9\u0015\u0005\u0001\u001b\u0005C\u0001\u0014B\u0013\t\u

扫描二维码推送至手机访问。

版权声明:本文由51Blog发布,如需转载请注明出处。

本文链接:https://www.51blog.vip/?id=244

分享给朋友:

“Scala面向对象” 的相关文章

Go Vue3 CMS办理后台(前后端别离形式)

Go Vue3 CMS办理后台(前后端别离形式)

本后台运用前后端别离形式开发,前端UI为Vue3+Ant Design Vue,后端Api为Go+Gin,解耦前后端逻辑,使开发更专心 技能栈 前端:Vue3,Ant Design Vue,Axios,分页,OTP动态码登录 后端:Go,Gin,Gorm,Mysql,Docker,JWT,跨域,...

java重定向,什么是请求重定向?

在Java中,重定向通常指的是将用户从一个URL重定向到另一个URL。这可以通过几种不同的方式实现,具体取决于你是在Servlet、JSP还是其他Java应用程序上下文中工作。 1. 使用Servlet重定向在Servlet中,你可以使用`HttpServletResponse`对象的`sendRe...

为什么程序员鄙视php,PHP的历史与现状

为什么程序员鄙视php,PHP的历史与现状

1. 技术特点:PHP最初是为快速开发网站而设计的脚本语言,它的语法简单、易学,但也因此被一些程序员认为不够严谨和高效。随着技术的发展,一些程序员认为PHP在性能、扩展性和安全性方面存在不足。2. 历史背景:PHP在互联网的早期阶段非常流行,许多网站和应用程序都是用PHP开发的。随着时间的推移,其他...

c语言按位取反

c语言按位取反

在C语言中,按位取反可以通过按位取反运算符 `~` 来实现。这个运算符会将操作数的每一位都取反,即0变成1,1变成0。下面是一个简单的例子,演示如何使用按位取反运算符:```cinclude int main { int num = 5; // 二进制表示为 101 int invert...

python中join的用法,python中join的用法和作用

python中join的用法,python中join的用法和作用

Python中join函数的用法详解在Python编程中,字符串的连接操作是非常常见的。`join()`函数是Python中用于连接字符串、元组、列表等序列元素的内置函数,它提供了灵活且高效的字符串连接方式。本文将详细介绍`join()`函数的用法,包括语法、参数、返回值以及一些实际应用场景。 1...

python下载官网,什么是Python?

您可以通过以下链接访问Python官网的下载页面,选择适合您操作系统的Python版本进行下载:在下载页面,您可以根据自己的操作系统(如Windows、macOS、Linux)选择合适的安装包版本。请确保您的设备满足Python的安装要求。Python官方下载指南:轻松获取并安装Python环境什么...