java基础之面向对象

面向对象是一种编程范式,它将程序中的数据和操作封装在对象中,并通过这些对象进行交互和通信。下面是一些面向对象的主要内容:

类和对象:

类是一个模板或蓝图,用于定义对象的属性(数据)和行为(方法)。
对象是类的实例,具有自己的状态(属性值)和行为(方法调用)。

封装:私有化

Java 中,封装是一种面向对象编程的基本概念,它指的是将数据和方法包装在一个类中,并对外部世界隐藏其实现细节,只暴露出一些公共接口供其他类进行访问。这样可以有效地保护数据,防止外部对象直接访问和修改类中的属性和方法,提高程序的安全性和可维护性。同时也使得代码更加模块化,易于扩展和重构。

Java 中的封装主要通过访问修饰符来实现,常用的有 private、protected、public 和默认访问修饰符。其中,private 访问修饰符表示只能在当前类中访问该属性或方法,其他类无法访问;protected 访问修饰符表示只能在当前类和其子类中访问该属性或方法;public 访问修饰符表示可以在任何地方访问该属性或方法;默认访问修饰符表示只能在同一个包中访问该属性或方法。

以下是一个简单的 Java 类,演示了如何使用封装:

public class Car {
    private String brand;
    private String color;
    private int speed = 0;
    
    public Car(String brand, String color) {
        this.brand = brand;
        this.color = color;
    }
    
    public void accelerate(int acceleration) {
        speed += acceleration;
    }
    
    public void brake(int deceleration) {
        speed -= deceleration;
    }
    
    public int getSpeed() {
        return speed;
    }
}

// 创建一个Car对象
Car myCar = new Car("Toyota", "Red");

// 封装的属性可以通过对象访问
System.out.println(myCar.getBrand());  // 输出:Toyota
System.out.println(myCar.getColor());  // 输出:Red

// 封装的方法也可以通过对象调用
myCar.accelerate(20);
System.out.println(myCar.getSpeed());  // 输出:20

myCar.brake(10);
System.out.println(myCar.getSpeed());  // 输出:10

在上述示例中,Car 类封装了三个私有属性:brand(品牌)、color(颜色)和 speed(速度),并提供了公共的方法来访问和操作这些属性。其他类无法直接访问 Car 类的私有属性,只能通过公共方法进行访问和修改。

封装的好处包括:

提高了代码的安全性和可维护性。
隐藏了实现细节,使得对外部的影响降到最小。
保护了数据的完整性和一致性,防止数据被误用或篡改。
使代码更加模块化,易于扩展和重构。

继承:关键词extends

继承是一种机制,允许一个类继承另一个类的属性和方法。
子类继承父类的特性,同时可以添加自己的特定特征。
继承提供了代码重用和层次化组织的能力。

继承是面向对象编程中的一种重要概念,它允许一个类(称为子类或派生类)从另一个类(称为父类或基类)继承属性和方法。通过继承,子类可以重用父类的代码,并且可以在此基础上添加新的属性和方法,实现代码的复用和扩展。

以下是一个简单的 Java 示例,演示了如何使用继承:

// 定义一个父类 Animal
class Animal {
    private String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    public void eat() {
        System.out.println(name + " is eating.");
    }
}

// 定义一个子类 Dog,继承自 Animal
class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }
    
    public void bark() {
        System.out.println("Woof woof!");
    }
}

// 创建一个 Dog 对象,并调用继承的方法和子类中的方法
Dog myDog = new Dog("Buddy");

myDog.eat();  // 输出:Buddy is eating.
myDog.bark();  // 输出:Woof woof!

在上述示例中,Animal 类是父类,Dog 类是子类。Dog 类通过使用 extends 关键字继承了 Animal 类,从而获得了父类中的属性和方法。子类可以通过调用 super() 方法来调用父类的构造函数,以初始化继承的属性。

通过继承,Dog 类可以调用 Animal 类中的 eat() 方法,并且还可以添加自己独有的 bark() 方法。这样,我们既可以重用父类的代码,又可以根据子类的特殊需求进行代码扩展。

继承的主要好处包括:

代码复用:子类可以继承父类的属性和方法,避免了重复编写相同的代码。
继承层级:可以通过继承构建类的层级结构,使得代码更加有组织性和易于理解。
支持多态:通过继承,可以实现多态性,即不同子类对象可以以相同的方式被处理。

需要注意的是,Java 中只支持单继承,即一个类只能继承自一个父类。但是,Java 提供了接口(interface)来实现多继承的某些功能。此外,当子类继承父类时,子类可以覆盖(重写)父类的方法,以实现自己的特定行为。

多态:子类对象指向

多态指的是同一个方法可以在不同的对象上产生不同的行为。
多态提供了灵活性,使得不同类型的对象可以以相同的方式进行操作。
多态通过方法的重写和方法的重载来实现。

在面向对象编程中,多态是指相同的操作作用于不同的对象上会产生不同的行为。具体来说,在Java中,多态性可以通过继承和方法重写来实现。下面是一个简单的Java示例,演示了多态的概念:

// 定义一个父类 Animal
class Animal {
    public void makeSound() {
        System.out.println("Some sound");
    }
}

// 定义子类 Dog,覆盖父类的 makeSound 方法
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Bark!");
    }
}

// 定义子类 Cat,覆盖父类的 makeSound 方法
class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        Animal myCat = new Cat();

        myDog.makeSound();  // 输出:Bark!
        myCat.makeSound();  // 输出:Meow!
    }
}

在这个例子中,我们定义了一个父类Animal,以及两个继承自Animal的子类Dog和Cat。在父类Animal中,定义了一个makeSound方法,然后在子类Dog和Cat中分别重写了这个方法。在Main类的main方法中,我们创建了一个Dog对象和一个Cat对象,并将它们赋值给Animal类型的引用。然后分别调用了它们的makeSound方法。

由于Java中的动态绑定机制,虽然myDog和myCat都是Animal类型的引用,但它们实际指向的是不同的子类对象。因此,当调用makeSound方法时,实际上调用的是对应子类的重写方法,从而产生了不同的行为。

这就是多态的体现:相同的操作(调用makeSound方法)作用于不同的对象(Dog和Cat),产生了不同的行为(Bark和Meow)。这种灵活的行为表现形式使得程序更易于扩展和维护。
接口:关键词:implements

接口定义了一组抽象方法,描述了对象所支持的操作。
类可以实现一个或多个接口,通过实现接口中的方法来定义自己的行为。
接口提供了代码的松耦合性,使得不同类之间可以进行交互和通信。

在面向对象编程中,接口是一种定义了一组方法签名的抽象类型。接口可以被类实现,从而使得类能够遵循接口定义的行为规范。以下是一个简单的Java示例,演示了接口的概念:

// 定义一个接口Animal
interface Animal {
    void makeSound();
}

// 定义一个类Dog,实现Animal接口
class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Bark!");
    }
}

// 定义一个类Cat,实现Animal接口
class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        Animal myCat = new Cat();

        myDog.makeSound();  // 输出:Bark!
        myCat.makeSound();  // 输出:Meow!
    }
}

在这个例子中,我们定义了一个接口Animal,其中声明了一个方法makeSound。然后,我们分别创建了两个类Dog和Cat,并且它们都实现了Animal接口,并实现了makeSound方法。

在Main类的main方法中,我们创建了一个Dog对象和一个Cat对象,并将它们赋值给Animal类型的引用。然后调用它们的makeSound方法。

通过接口的使用,我们可以实现多态性。尽管myDog和myCat都是Animal类型的引用,但它们实际上指向了不同的对象。然而,由于它们都实现了Animal接口,并且遵循了makeSound方法的规范,因此可以调用makeSound方法,产生不同的行为。

接口的好处包括:

定义契约:接口定义了一组方法签名,作为类之间的契约,使得不同的类可以实现相同的接口,从而保证了一致的行为。
实现多继承:通过实现多个接口,一个类可以具有多个接口的特性,实现了某种程度上的多继承。
代码解耦:通过依赖接口而非具体实现类,可以将代码解耦,提高代码的灵活性和可维护性。

需要注意的是,接口中的方法默认是公共和抽象的,因此在实现接口时必须实现接口中声明的所有方法。同时,一个类可以实现多个接口,但只能继承一个父类。
抽象类:关键词:abstract

抽象类是一种不能实例化的类,它定义了一组抽象方法。
抽象方法没有具体的实现,需要在子类中进行实现。
抽象类可以包含具体的方法,子类可以直接继承和使用。

在面向对象编程中,抽象类是一种不能实例化的类,用于定义一组相关类的公共行为和属性。抽象类可以包含抽象方法和具体方法,并且可以被子类继承和扩展。以下是一个简单的Java示例,演示了抽象类的概念:

// 定义一个抽象类Animal
abstract class Animal {
    private String name;

    public Animal(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    // 定义一个抽象方法makeSound
    public abstract void makeSound();
}

// 定义一个具体类Dog,继承自Animal
class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println("Bark!");
    }
}

// 定义一个具体类Cat,继承自Animal
class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println("Meow!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog("Doggy");
        Animal myCat = new Cat("Kitty");

        System.out.println(myDog.getName() + " says:");
        myDog.makeSound();  // 输出:Bark!

        System.out.println(myCat.getName() + " says:");
        myCat.makeSound();  // 输出:Meow!
    }
}

在这个例子中,我们定义了一个抽象类Animal,其中包含了一个抽象方法makeSound和一个具体方法getName。抽象类Animal还有一个私有属性name,以及一个构造方法用于初始化name。

然后,我们定义了两个具体类Dog和Cat,它们都继承自Animal类,并实现了makeSound方法。这些具体类必须实现抽象类Animal中的所有抽象方法。

在Main类的main方法中,我们创建了一个Dog对象和一个Cat对象,并将它们赋值给Animal类型的引用。通过这种方式,我们可以访问抽象类Animal中定义的方法和属性。

通过抽象类的使用,我们可以实现代码的重用和扩展。抽象类提供了一种模板或基类的概念,可以定义通用的行为和属性,而具体类则可以根据需要进行进一步的定制和扩展。

需要注意的是,抽象类不能被实例化,只能作为基类被其他类继承。同时,如果一个类继承了抽象类,它必须实现抽象类中的所有抽象方法,除非该类本身也是一个抽象类。
设计模式:

设计模式是一套解决常见问题的经验总结和最佳实践。
它们提供了在特定情境下的可重用解决方案,提高了代码的可维护性和可扩展性。
常见的设计模式包括单例模式、工厂模式、观察者模式等。

设计模式是一种经过实践证明的、被广泛采用的面向对象编程技巧。以下是三个常见的设计模式示例:

单例模式

单例模式是一种保证一个类只有一个实例,并提供全局访问点的设计模式。以下是一个简单的Java示例,演示了单例模式的概念:

// 定义一个单例类Singleton
class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

public class Main {
    public static void main(String[] args) {
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        System.out.println(s1 == s2);  // 输出:true
    }
}

在这个例子中,我们定义了一个单例类Singleton,其中包含一个私有静态属性instance和一个私有构造方法。getInstance方法通过检查instance是否为空来返回Singleton的唯一实例。

在Main类的main方法中,我们创建了两个Singleton对象s1和s2,并比较它们的引用是否相等。由于Singleton类只有一个实例,因此s1和s2实际上是同一个对象。通过使用单例模式,我们可以保证某些类只有一个实例,从而避免了重复创建对象的开销和可能的线程安全问题。

工厂模式

工厂模式是一种将对象的创建和使用分离的设计模式。以下是一个简单的Java示例,演示了工厂模式的概念:

// 定义一个接口Shape
interface Shape {
    void draw();
}

// 定义具体类Circle、Rectangle和Square,实现Shape接口
class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing circle...");
    }
}

class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing rectangle...");
    }
}

class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing square...");
    }
}

// 定义一个工厂类ShapeFactory,用于创建Shape对象
class ShapeFactory {
    public static Shape getShape(String type) {
        if (type.equalsIgnoreCase("circle")) {
            return new Circle();
        } else if (type.equalsIgnoreCase("rectangle")) {
            return new Rectangle();
        } else if (type.equalsIgnoreCase("square")) {
            return new Square();
        } else {
            return null;
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Shape circle = ShapeFactory.getShape("circle");
        Shape rectangle = ShapeFactory.getShape("rectangle");
        Shape square = ShapeFactory.getShape("square");

        circle.draw();
        rectangle.draw();
        square.draw();
    }
}

在这个例子中,我们定义了一个接口Shape,其中包含一个抽象方法draw。然后,我们定义了三个具体类Circle、Rectangle和Square,它们都实现了Shape接口,并实现了draw方法。

接着,我们定义了一个工厂类ShapeFactory,它包含一个静态方法getShape来创建Shape对象。根据传入的参数type,ShapeFactory可以创建不同类型的Shape对象。

在Main类的main方法中,我们使用ShapeFactory来创建Circle、Rectangle和Square对象,并调用它们的draw方法。通过使用工厂模式,我们可以将对象的创建和使用分离,从而使得代码更加灵活和易于维护。

观察者模式

观察者模式是一种在对象之间定义一对多的依赖关系,使得当一个对象状态发生改变时,所有依赖于它的对象都会得到通知并自动更新的设计模式。以下是一个简单的Java示例,演示了观察者模式的概念:

// 定义一个接口Observer
interface Observer {
    void update(int value);
}

// 定义具体类BinaryObserver、OctalObserver和HexObserver,实现Observer接口
class BinaryObserver implements Observer {
    @Override
    public void update(int value) {
        System.out.println("Binary string: " + Integer.toBinaryString(value));
    }
}

class OctalObserver implements Observer {
    @Override
    public void update(int value) {
        System.out.println("Octal string: " + Integer.toOctalString(value));
    }
}

class HexObserver implements Observer {
    @Override
    public void update(int value) {
        System.out.println("Hex string: " + Integer.toHexString(value));
    }
}

// 定义一个主题Subject,包含一个列表observers,用于存储观察者对象
class Subject {
    private List<Observer> observers = new ArrayList<>();
    private int value;

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
        notifyObservers();
    }

    public void attach(Observer observer) {
        observers.add(observer);
    }

    public void detach(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(value);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Subject subject = new Subject();

        Observer binaryObserver = new BinaryObserver();
        Observer octalObserver = new OctalObserver();
        Observer hexObserver = new HexObserver();

        subject.attach(binaryObserver);
        subject.attach(octalObserver);
        subject.attach(hexObserver);

        System.out.println("First state change: 15");
        subject.setValue(15);

        subject.detach(hexObserver);

        System.out.println("\nSecond state change: 10");
        subject.setValue(10);
    }
}

在这个例子中,我们定义了一个接口Observer,其中包含一个抽象方法update。然后,我们定义了三个具体类BinaryObserver、OctalObserver和HexObserver,它们都实现了Observer接口,并实现了update方法。

接着,我们定义了一个主题Subject,它包含一个列表observers,用于存储观察者对象。Subject类还包含setValue方法,用于设置value属性并通知所有观察者对象进行更新。

在Main类的main方法中,我们创建了一个Subject对象subject,并分别创建了三个Observer对象binaryObserver、octalObserver和hexObserver。然后,我们将这些观察者对象注册到主题subject中,并设置了value属性的值。当value属性发生变化时,所有观察者对象都会收到通知并更新自己的状态。

通过使用观察者模式,我们可以实现对象之间的松耦合,从而使得代码更加灵活和易于扩展。主题Subject和观察者Observer之间没有直接的依赖关系,它们之间只通过一个共同的接口进行通信,从而使得代码更加易于维护和测试。

posted @   mm大魔王  阅读(19)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示