BUG Wrong error raised for OneVsRestClassifier with a sub-estimator that doesn't allow partial_fit

### Describe the bug

When using the `OneVsRestClassifier` with a sub-estimator, that doesn't have `partial_fit` implemented, a misleading error message is shown: `AttributeError: This 'OneVsRestClassifier' has no attribute 'partial_fit'`.

Though, `OneVsRestClassifier` does implement `partial_fit`, but the underlying estimator doesn't.

There is an appropriate error raising already implemented in
https://github.com/scikit-learn/scikit-learn/blob/f1e89363f6777155a25b3574db9f0fc5c21a8c51/sklearn/multiclass.py#L437

```python
            if not hasattr(self.estimator, "partial_fit"):
                raise ValueError(
                    ("Base estimator {0}, doesn't have partial_fit method").format(
                        self.estimator
                    )
                )
```
But it's not run, because the AttributeError from the `@available_if` decorator/descriptor thing pops up earlier.

I'd like to learn about that, repair that and add a test to make sure this doesn't happen again by accident.
I will also check if other methods from the multiclass classifiers are also affected.

Is it alright if I go ahead with this?

### Steps/Code to Reproduce

```python
from sklearn.datasets import load_iris
from sklearn.multiclass import OneVsRestClassifier
from sklearn.linear_model import LogisticRegression
import numpy as np

iris = load_iris()
sample_weight = np.ones_like(iris.target, dtype=np.float64)
clf = OneVsRestClassifier(
estimator=LogisticRegression(random_state=42)
)
clf.partial_fit(iris.data, iris.target)
```

### Expected Results

`ValueError:  LogisticRegression doesn't have partial_fit method`

### Actual Results

`AttributeError: This 'OneVsRestClassifier' has no attribute 'partial_fit'`.

### Versions

```shell
System:
    python: 3.10.6 (main, Oct 10 2022, 12:43:33) [GCC 9.4.0]
executable: /home/stefanie/.pyenv/versions/3.10.6/envs/scikit-learn_dev/bin/python
   machine: Linux-5.15.0-91-generic-x86_64-with-glibc2.31

Python dependencies:
      sklearn: 1.5.dev0
          pip: 23.3.2
   setuptools: 63.2.0
        numpy: 1.26.0
        scipy: 1.11.3
       Cython: 0.29.34
       pandas: 2.1.4
   matplotlib: 3.8.0
       joblib: 1.3.2
threadpoolctl: 3.1.0

Built with OpenMP: True

threadpoolctl info:
       user_api: blas
   internal_api: openblas
         prefix: libopenblas
       filepath: /home/stefanie/.pyenv/versions/3.10.6/envs/scikit-learn_dev/lib/python3.10/site-packages/numpy.libs/libopenblas64_p-r0-0cf96a72.3.23.dev.so
        version: 0.3.23.dev
threading_layer: pthreads
   architecture: SkylakeX
    num_threads: 8

       user_api: blas
   internal_api: openblas
         prefix: libopenblas
       filepath: /home/stefanie/.pyenv/versions/3.10.6/envs/scikit-learn_dev/lib/python3.10/site-packages/scipy.libs/libopenblasp-r0-23e5df77.3.21.dev.so
        version: 0.3.21.dev
threading_layer: pthreads
   architecture: SkylakeX
    num_threads: 8

       user_api: openmp
   internal_api: openmp
         prefix: libgomp
       filepath: /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0
        version: None
    num_threads: 8
```

COMMENT:
I merged #28198 so we can leverage it.

When I asked for tests, I think the pattern used by @thomasjpfan could be used here as well:
https://github.com/scikit-learn/scikit-learn/pull/28198/files#diff-a9256841e2ca6477c25abca76d3b5d785b69160e055765031b3e9cd8ae3b7b51R67-R72

Labels: Bug